PropertyGrid zur Laufzeit mit dem TypeConverter beeinflussen
Frank Dzaebel, erstellt am: 19.05.2007, zuletzt geändert: 19.05.2007
Kategorie:PropertyGrid, .NET-Version:2.0, [Download]

Man kann Attribute beim PropertyGrid zur Laufzeit (quasi) beeinflussen, wenn man die Klasse, deren Objekt auf das SelectedObject festgelegt wurde, mit einem TypeConverter-Attribut versieht.



Siehe auch:
- Kategorien eines PropertyGrid's sortieren
-
Dynamische "Attribut-Änderung" beim PropertyGrid


using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Reflection;

namespace FilterPropertyGrid
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    public static string Kategorie = "Erste Kategorie";

    Person person = new Person();
    private void Form1_Load(object sender, EventArgs e)
    {
      propertyGrid1.SelectedObject = person;
    }

    private void btnKategorie_Click(object sender, EventArgs e)
    {
      Kategorie = "Zweite Kategorie";
      propertyGrid1.SelectedObject = person;
    }
  }

  [TypeConverter(typeof(FilterTypeConverter))]
  class Person
  {
    string name = "Hans Mustermann";
    [Filter("Name")]
    public string Name
    {
      get { return name; }
      set { name = value; }
    }

    int alter = 42;
    [Filter("Alter")]
    public int Alter
    {
      get { return alter; }
      set { alter = value; }
    }
  }

  [AttributeUsage(AttributeTargets.All)]
  public class FilterAttribute : Attribute
  {
    string filter;
    public FilterAttribute(string filter)
    {
      this.filter = filter;
    }
  }

  class FilterTypeConverter : TypeConverter
  {
    public override PropertyDescriptorCollection GetProperties(
      ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
      MyPropertyDescriptor[] mpd = new MyPropertyDescriptor[2];
      mpd[0] = new MyPropertyDescriptor("Name", new FilterAttribute("Name"));
      mpd[1] = new MyPropertyDescriptor("Alter", new FilterAttribute("Alter"));
      return new PropertyDescriptorCollection(mpd);
    }

    public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    {
      return true;
    }

    protected class MyPropertyDescriptor : TypeConverter.SimplePropertyDescriptor
    {
      /// <summary>SpaltenName oder Wert</summary>
      string wert;

      public MyPropertyDescriptor(string value, FilterAttribute attribute)
        : base(typeof(Person), value, typeof(string),
          new Attribute[]{new BrowsableAttribute(true), attribute, 
          new CategoryAttribute(Form1.Kategorie) })
      {
        wert = value;
      }

      public override AttributeCollection Attributes
      {
        get
        {
          return base.CreateAttributeCollection();
        }
      }

      protected override object GetInvocationTarget(Type type, object instance)
      {
        return base.GetInvocationTarget(type, instance);
      }

      public override object GetValue(object component)
      {
        if (!isSet)
        {
          PropertyInfo pi = component.GetType().GetProperty(wert);
          return pi.GetValue(component, null);
        }
        else return wert;
      }

      bool isSet = false;

      public override void SetValue(object component, object value)
      {
        isSet = true;
        PropertyInfo pi = component.GetType().GetProperty(wert);
        if (pi == null) { wert = value as string; return; }
        TypeConverter tc = TypeDescriptor.GetConverter(pi.PropertyType);
        object val = tc.ConvertFromString(value as string);
        pi.SetValue(component, val, null);
        wert = value as string;
      }
    }
  }
}