none
Aufruf in einer Property-Klasse RRS feed

  • Frage

  • Salü zäme

    Ich habe eine Property-Klasse, welche zehmal eine Klasse eingebunden hat. Normalerweise spreche ich dann diese Klassen mit einer Eigenschaft an. (zB. propertyGrid.Sonne.Farbe=Color.Red).
    Nun bekomme ich aber aus einem Event nur die Mitteilung, dass die Farbe im Grid zur Eigenschaft "Sonne" (String-Wert) gewechselt werden muss. Da ich mir dieser Nachricht (Value) aber die Eigenschaft nicht ansprechen kann, suche ich einen "gescheiten" Weg, wie ich die Farbe dieses Objetes im Proerty-Grid nun ändern kann.
    Ich habe mich mit einer switch/case-Funktion beholfen, doch dies sieht einfach so doof und mühselig aus.

    Gibt es andere Möglichkeiten wie ich mit einem StringWert auf die entsprechende und gleichnamige Eigenschaft einer Klasse zugreifen könnte?

    Ich hoffe meine Frage konnte ich einigermassen verständlich formulieren...

    Danke und Gruss
    Jakob

    Dienstag, 6. Juli 2010 13:19

Antworten

  • Hallo Jakob,

    wenn Du das entsprechend der INotifyPropertyChanged Schnittstelle implementiert hast,
    so ist der direkteste Ansatz allerdings ein switch über PropertyName.
    Leider hat man dort keine Übergaben für den Wert (alter und neuer) vorgesehen.

    Da die Schnittstelle beim WPF-MVVM Muster sehr häufig vorkommt,
    ist einiges dazu geschrieben worden, siehe z. B.:

    http://stackoverflow.com/questions/141370/inotifypropertychanged-property-name-hardcode-vs-reflection
    und auch: http://compositeextensions.codeplex.com/Thread/View.aspx?ThreadId=53731

    Dabei geht es zunächst um das Auslösen, wobei der Code vielfach am anderen Ende
    ebenso eiingesetzt werden kann, wie z. B. TypeDescriptor.GetProperties -
    bis zu ganzen Ergänzungen, u. a.:
    INotifyPropertyChanged and beyond - Part I
    INotifyPropertyChanged and beyond - Part II

    Welcher Weg am Ende der beste ist, kann man nicht abschließend sagen.
    Beachten sollte man, das beim WPF MVVM Muster das Ereignis sehr häufig
    aufgerufen wird. Und man das Auflösen von Namen (insbeondere über die
    relativ langsame Reflektion) nur vornehmen sollte, wenn es notwendig ist.

    Gruß Elmar

    • Als Antwort markiert Jakob.Brunner Mittwoch, 7. Juli 2010 11:53
    Dienstag, 6. Juli 2010 15:02
    Beantworter
  • Hallo Jakob,

    Bei einem PropertyGrid bräuchte man ggf. weder Reflection noch INotifyPropertyChanged, da der alte Wert schon in den PropertyValueChangedEventArgs steht:

     public partial class Form1 : Form
     {
      public Form1()
      {
       InitializeComponent();
      }
    
      Property p = new Property();
    
      private void Form1_Load(object sender, EventArgs e)
      {
       p.Sonne = new MeineKlasse() { Farbe = Color.Red };
       p.Mond = new MeineKlasse() { Farbe = Color.Blue };
       propertyGrid1.SelectedObject = p;
       propertyGrid1.PropertyValueChanged += PropertyGrid1_PropertyValueChanged;
      }
    
      void PropertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
      {
       var pd = propertyGrid1.SelectedGridItem.PropertyDescriptor;
       GridItem gi = e.ChangedItem; var oldValue = e.OldValue;
       MessageBox.Show("Eigenschaft: '" + pd.DisplayName + "' des Typs: '" +
        pd.PropertyType.Name + "' wurde von Wert: '" + oldValue + "' auf den Wert: '" +
        gi.Value + "' gesetzt.");
      }
    
      class Property
      {
       public MeineKlasse Sonne { get; set; }
       public MeineKlasse Mond { get; set; }
       // ... 10 mal
      }
    
      [TypeConverter(typeof(ExpandableObjectConverter))]
      class MeineKlasse
      {
       public Color Farbe { get; set; }
    
       public override string ToString()
       {
        return Farbe.ToString();
       }
      }
     }
    

    Ich weiss nur nicht, wessen Farbe Du jetzt auf das Event hin ändern willst.

     


    ciao Frank
    • Als Antwort markiert Jakob.Brunner Mittwoch, 7. Juli 2010 11:53
    Mittwoch, 7. Juli 2010 07:53
  • Gibt es andere Möglichkeiten wie ich mit einem StringWert auf die entsprechende und gleichnamige Eigenschaft einer Klasse zugreifen könnte?

    Und ansonsten kannst Du die Property über den Namen natürlich auch über GetProperty bekommen:

     Color hintergrund = (Color)this.GetType().GetProperty("BackColor").GetValue(this, null);
     MessageBox.Show(hintergrund.ToString());

    ciao Frank
    • Als Antwort markiert Jakob.Brunner Mittwoch, 7. Juli 2010 11:53
    Mittwoch, 7. Juli 2010 08:05

Alle Antworten

  • Hallo Jakob,

    wenn Du das entsprechend der INotifyPropertyChanged Schnittstelle implementiert hast,
    so ist der direkteste Ansatz allerdings ein switch über PropertyName.
    Leider hat man dort keine Übergaben für den Wert (alter und neuer) vorgesehen.

    Da die Schnittstelle beim WPF-MVVM Muster sehr häufig vorkommt,
    ist einiges dazu geschrieben worden, siehe z. B.:

    http://stackoverflow.com/questions/141370/inotifypropertychanged-property-name-hardcode-vs-reflection
    und auch: http://compositeextensions.codeplex.com/Thread/View.aspx?ThreadId=53731

    Dabei geht es zunächst um das Auslösen, wobei der Code vielfach am anderen Ende
    ebenso eiingesetzt werden kann, wie z. B. TypeDescriptor.GetProperties -
    bis zu ganzen Ergänzungen, u. a.:
    INotifyPropertyChanged and beyond - Part I
    INotifyPropertyChanged and beyond - Part II

    Welcher Weg am Ende der beste ist, kann man nicht abschließend sagen.
    Beachten sollte man, das beim WPF MVVM Muster das Ereignis sehr häufig
    aufgerufen wird. Und man das Auflösen von Namen (insbeondere über die
    relativ langsame Reflektion) nur vornehmen sollte, wenn es notwendig ist.

    Gruß Elmar

    • Als Antwort markiert Jakob.Brunner Mittwoch, 7. Juli 2010 11:53
    Dienstag, 6. Juli 2010 15:02
    Beantworter
  • Hallo Jakob,

    Bei einem PropertyGrid bräuchte man ggf. weder Reflection noch INotifyPropertyChanged, da der alte Wert schon in den PropertyValueChangedEventArgs steht:

     public partial class Form1 : Form
     {
      public Form1()
      {
       InitializeComponent();
      }
    
      Property p = new Property();
    
      private void Form1_Load(object sender, EventArgs e)
      {
       p.Sonne = new MeineKlasse() { Farbe = Color.Red };
       p.Mond = new MeineKlasse() { Farbe = Color.Blue };
       propertyGrid1.SelectedObject = p;
       propertyGrid1.PropertyValueChanged += PropertyGrid1_PropertyValueChanged;
      }
    
      void PropertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
      {
       var pd = propertyGrid1.SelectedGridItem.PropertyDescriptor;
       GridItem gi = e.ChangedItem; var oldValue = e.OldValue;
       MessageBox.Show("Eigenschaft: '" + pd.DisplayName + "' des Typs: '" +
        pd.PropertyType.Name + "' wurde von Wert: '" + oldValue + "' auf den Wert: '" +
        gi.Value + "' gesetzt.");
      }
    
      class Property
      {
       public MeineKlasse Sonne { get; set; }
       public MeineKlasse Mond { get; set; }
       // ... 10 mal
      }
    
      [TypeConverter(typeof(ExpandableObjectConverter))]
      class MeineKlasse
      {
       public Color Farbe { get; set; }
    
       public override string ToString()
       {
        return Farbe.ToString();
       }
      }
     }
    

    Ich weiss nur nicht, wessen Farbe Du jetzt auf das Event hin ändern willst.

     


    ciao Frank
    • Als Antwort markiert Jakob.Brunner Mittwoch, 7. Juli 2010 11:53
    Mittwoch, 7. Juli 2010 07:53
  • Gibt es andere Möglichkeiten wie ich mit einem StringWert auf die entsprechende und gleichnamige Eigenschaft einer Klasse zugreifen könnte?

    Und ansonsten kannst Du die Property über den Namen natürlich auch über GetProperty bekommen:

     Color hintergrund = (Color)this.GetType().GetProperty("BackColor").GetValue(this, null);
     MessageBox.Show(hintergrund.ToString());

    ciao Frank
    • Als Antwort markiert Jakob.Brunner Mittwoch, 7. Juli 2010 11:53
    Mittwoch, 7. Juli 2010 08:05