Forum: PC-Programmierung C# INotifyPropertyChanged, auf geänderte Eigenschaft zugreifen


von Alex (Gast)


Lesenswert?

Hallo,

ich habe eine Klasse geschrieben, die die INotifyPropertyChanged 
Schnittstelle implementiert und die eine PropertyChangedEvent auslöst, 
wenn sich eine ihrer Eigenschaften ändert.
Wie kann ich nun im EventHandler auf die geänderte Eigenschaft 
zugreifen?
Der EventHandler sieht so aus:
1
private void On_PropertyChanged(object sender, PropertyChangedEventArgs e)
2
{
3
                      
4
}

e hat eine Eigenschaft vom Typ String namens e.PropertyName, in der der 
Name der geänderten Klasseneigenschaft steht. Nun weiß ich nicht, wie 
ich mit Hilfe des Strings auf diese Klasseneigenschaft zugreifen kann, 
um z.B. den geänderten Wert auszulesen und zu verwenden. Stichwort 
"Reflection" hab ich schon mal aufgeschnappt, komme aber nicht weiter.

Grüße, Alex

von Arc N. (arc)


Lesenswert?


von Alex (Gast)


Lesenswert?

Hallo Arc Net

Danke für den Hinweis. Ausgehen von dem, was ich dort und auch so noch 
im Netz gefunde habe, heb ich ein bisschen probiert. Es geht, allerdings 
scheint das noch nicht der Weisheit letzter Schluss zu sein. Z.B. 
erscheint es mir "komisch", dass ich eine Methode von sender aufrufe, 
der ich dann sender übergebe. Auch kann man ja zur Laufzeit nicht 
wissen, ob ich das einfach in bool typecasten kann. Ich mach das jetz 
einfachm, weil ich weiß das die Property bool ist, aber sauber ist das 
doch so nicht, oder? Kannst Du mal bitte einen Blick darauf werfen und 
gegebenenfalls was bemängeln.
1
 private void On_PropertyChanged(object sender, PropertyChangedEventArgs e)
2
        {
3
            object IsOnline = sender.GetType().GetProperty(e.PropertyName).GetValue(sender,null);
4
            object SenderNo = sender.GetType().GetProperty("SenderNo").GetValue(sender, null);
5
            
6
            switch((int)SenderNo)
7
            {
8
                case 0:
9
                    if ((bool)IsOnline)
10
                    {
11
                        labelRadioStatus.Text = "online";
12
                        labelRadioStatus.BackColor = Color.Green;
13
                    }
14
                    else
15
                    {
16
                        labelRadioStatus.Text = "offline";
17
                        labelRadioStatus.BackColor = Color.Red;
18
                    }
19
                    break;
20
                case 1:
21
                    if ((bool)IsOnline)
22
                    {
23
                        labelRadioStatus.Text = "online";
24
                        labelRadioStatus.BackColor = Color.Green;
25
                    }
26
                    else
27
                    {
28
                        labelRadioStatus.Text = "offline";
29
                        labelRadioStatus.BackColor = Color.Red;
30
                    }
31
                    
32
                    break;
33
                default:
34
                    break;
35
            }

Danke, Alex

von Christian R. (mrrotzi)


Lesenswert?

Welche Art von Applikation schreibst du da?

Winforms? WPF?

Kannst du nicht sauberes DataBinding machen?


Wieso castest du nicht "sender" auf den Typ deines Objekts?


var o = sender as "ClassName"

dann kannst du auf deine Eigenschaften zugreifen:

o.IsOnline
o.SenderNo

nicht??

Grüße,
Christian

von Alex (Gast)


Lesenswert?

Hallo Christian,

ich schreibe an einer Windows Forms Anwendung. Das mit dem typecast 
hatte ich probiert. Was mir Probleme macht, ist der Zugriff auf die 
Eigenschaft mit Hilfe des e.PropertyName.
Also etwa so (natürlich syntaktisch völliger Unfug, aber zum 
Verständnis):

var o = sender as myClass;
... = o.(e.PropertyName);

Sozusagen anhand e.PropertyName schauen, welchen Typ e.PropertyName in 
myClass hat, Variable entsprechend deklarieren und dann den Wert aus der 
Klasseninstanz zuweisen.

Eine Frage noch. Wie verhält sich das bei der Datenbindung. Müssen da 
Datenquelle und Ziel vom selben Typ sein. In meinem Fall soll ja auf 
Änderung einer Bool-Variable hin ein Textfeld geändert werden.

Danke und Gruß, Alex

von bluppdidupp (Gast)


Lesenswert?

und warum nicht einfach:
1
myClass c = sender as myClass;
2
if (e.PropertyName=="mein_property")
3
{
4
    bool bla=c.mein_property;
5
}

Den Typ einer Variable kann man übrigens sehr leicht überprüfen:
1
if (irgendeinObject is bool)
2
{
3
    // Yeah, irgendeinObject ist ein bool bzw. kann gefahrlos auf bool gecasted werden :D
4
}

von Christian R. (mrrotzi)


Lesenswert?

Alex,

Ich würde das auch so wie bluppdidupp beschrieben hat machen!
Immerhin bist du in deiner App Herr über die Klassen und
kannst e.PropertyName auswerten und dann direkt auf die entspr. 
Properties
zugreifen.

Um Fehler zu vermeiden, empfehle ich Konstanten für die 
Eigenschaftsnamen
einzuführen.


public class MyClass : INotifyPropertyChanged
{
 ...

 public bool IsOnline
 {
   get { return this._isOnline; }
   set
   {
     if(this._isOnline != value)
     {
       this._isOnline = value;
       NotifyPropertyChanged(PropertyNameIsOnline);
     }
   }
 }
 private bool _isOnline;
 public const string PropertyNameIsOnline = "IsOnline";
 ....
}


dann kannst du in den event handlern oder anderen Funktionen drauf 
zugreifen:


if(e.PropertyName == MyClass.PropertyNameIsOnline)
{
  .....
}


Es liegt natürlich am Entwickler dafür zu sorgen, die Konstanten immer
aktuell zu halten!

zur Datenbindungs-Frage:
In deinem Fall änderst du Text und Farbe - also würde ich hier o.a. 
Methodik implementieren.
Bei Winforms Apps habe ich selten Databinding eingesetzt. Grad mal bei 
ComboBoxen oder einem Data-Grid.
Data Binding fetzt erst so richtig in WPF oder Silverlight Apps!
Dort setzt man dann Konvertoren ein, wenn die Typen nicht zusammen 
passen.

Grüße,
Christian

von Alex (Gast)


Lesenswert?

Hallo liebe Helfende,

am Ende werde ich das wohl so, wie voergeschlagen, machen. Ich hatte nur 
gelesen, dass man den Zugriff auf die Properties von sender im 
Eventhandler via Reflection macht und dachte, dass so machen zu müssen, 
weil es die saubere Lösung wäre. Ich hab auch in 'nem engl. Forum einen 
Thread gelesen, wo jemand das machen wollte, ohne String-Literale zu 
verwenden. Also kein
1
if(e.PropertyName == "bestimmterString")
Warum, weiß ich jetzt nicht mehr genau. Ich wollte es quasi ganz elegant 
machen, bzw. so, wie man das halt macht, wenn es den einen Königweg 
geben sollte, Scheuklappen sozusagen.

@blubbdidubb:

if (irgendeinObject is bool)

wenn ich das so machen wollte, müsste ich ja das object auf jeden 
möglichen Typ testen. Das wäre unter Umständen ziemlich länglich.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.