Laden...

TextBox: PropertyChanged funktioniert nicht?

Erstellt von punkdevil vor 11 Jahren Letzter Beitrag vor 11 Jahren 6.489 Views
P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 11 Jahren
TextBox: PropertyChanged funktioniert nicht?

Hallo,

ich habe folgendes MainWindow:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBox Text="{Binding MyTextProperty, Mode=TwoWay}"/>
        <Button Height="20"/>
    </StackPanel>
</Window>

Dazu habe ich folgendes ViewModel:

class ViewModel : System.ComponentModel.INotifyPropertyChanged
    {
        public string MyTextProperty
        {
            get
            {
                return "MyText";
            }
            set
            {
                if (PropertyChanged != null) PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("MyTextProperty"));
            }
        }

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    }

Wenn ich jetzt Text in der TexBox ändere wird der Setter von MyTextPropertyx aufgerufen, darin löse ich das PropertyChanged-Event aus.
Müsste danach nicht die TextBox wieder in den Getter reinspringen und sich den neuen Wert holen?
Es passiert aber nichts. Ich hätte erwartet, egal was ich in der TextBox eingebe nach dem ich die TextBox verlasse steht wieder "MyText" drin.

Warum ist das nicht so?

692 Beiträge seit 2008
vor 11 Jahren

Hallo,

probier mal


 <TextBox Text="{Binding MyTextProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

Schöne Grüße
Quaneu

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 11 Jahren

UpdateSourceTrigger=PropertyChanged hat nur zur Folge, dass bei jeder Änderung des Textes (nicht erst bei LostFocus) in den Setter gesprungen wird.

692 Beiträge seit 2008
vor 11 Jahren

Das weiß ich 😃

Mich hat nur deine Aussage

Wenn ich jetzt Text in der TexBox ändere wird der Setter von MyTextPropertyx aufgerufen...

bisschen stutzig gemacht. Daher wollte ich dies nur erwähnen.

1.378 Beiträge seit 2006
vor 11 Jahren

//EDIT: Antwort revidiert... muss nochmal drüber nachdenken^^

//EDIT²: Also ich hätte hier eine Vermutung:

Properties werden oft nach dem Schema implementiert um rekursive Aufrufe durch Changed Events zu verhindern:


set
{
   if(_value != value)
   {
       _value=value;
       // handle changed events
   }
}

Ebenso merken sich die Properties der Controls ihre Werte und tun daher nur dann was, wenn sich wirklich etwas geändert hat und wenn das nicht der Fall ist, weil du immer den selben zurückgibst, wird natürlich der angezeigte Wert nicht verändert. Da kannst du noch so oft PropertyChanged feuern.

Lg, XXX

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 11 Jahren

@ xxsprod: Das ist nur ein Beispiel, deshalb gebe ich den gleichen Wert zurück.

1.378 Beiträge seit 2006
vor 11 Jahren

Genau deswegen funktionierts ja auch nicht - Wenn du jedesmal einen anderen oder den "richtigen" Wert zurück geben würdest, würde sich die Anzeige auch dementsprechend anpassen.

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 11 Jahren

@ xxxprod: Der Getter wird nur einmal aufgerufen (beim Start der Anwendung), er müsste doch aber bei jedem PropertyChanged-Event aufgerufen werden. Selbst wenn ich wollte kann ich gar keinen anderen Wert zurückliefern...

1.378 Beiträge seit 2006
vor 11 Jahren

Ok das lässt sich in deiner Konfiguration so erklären:

Das liegt am UpdateSourceTrigger welcher im Standardfall "LostFocus" ist. Da du nur ein Control in deiner Testapplikation hast ist es auch unmöglich dass dieses eine den Fokus verliert und daher wird set und get nie aufgerufen. Füge noch einen Button oder eine andere Tb ein dann wird der Setter und Getter auch beim Verlassen aufgerufen.

Alternativ kannst du wie Quaneu bereits in seinem Code erwähnt hat UpdateSourceTrigger auf PropertyChanged setzen.

Lg, XXX

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 11 Jahren

Ich habe ein zweites Control, es wird ja auch in den Setter gesprungen, nur eben nicht in den Getter, nachedm ich PropertyChnaged ausgelöst habe.

S
248 Beiträge seit 2008
vor 11 Jahren

Dein Code, aus dem Startposting, funktioniert bei mir wie erwartet (Update bei Fokusverlust).

Wie weisst du das ViewModel zu?

spooky

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 11 Jahren

Das ViewModel weise ich im Konstruktur dem DataContext zu:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.DataContext = new ViewModel();

            InitializeComponent();
        }
    }

Das heißt, nachdem du irgendwas eingegeben hast, steht nach dem LostFocus wieder "MyText" in der TextBox?

F
10.010 Beiträge seit 2004
vor 11 Jahren

Und du bist sicher das der DataContext vor InitializeComponent gesetzt werden sollte?

S
248 Beiträge seit 2008
vor 11 Jahren

Das heißt, nachdem du irgendwas eingegeben hast, steht nach dem LostFocus wieder "MyText" in der TextBox?

Wenn ich den Button anklicke setzt er den Text zurück.
Ich habe DataContext allerdings nach InitializeComponent() gesetzt.

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 11 Jahren

@FZelle: Gibt es einen Unterschied, ob man davor oder danach setzt? Ich habe es jetzt mal danach gemacht, das Ergebnis ist das gleiche.

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 11 Jahren

Ahh, jetzt habe ich das Problem gefunden. Ich habe ein .Net 3.5 Projekt, mit der Version 4.0 funktioniert es wie gewünscht.

F
10.010 Beiträge seit 2004
vor 11 Jahren

Klar gäbe es einen Unterschied.

Durch das setzen des DataContext wird intern auch ein DataContextChanged ausgelöst.
Machst Du das vorher, hört das keiner.

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 11 Jahren

@FZelle: Ich habe beide Varianten probiert, mit .Net 3.5 verhält sich das Beispiel anders als mit .Net4.0, egal ob ich den DataContext vor oder nach InitializeComponent() setze.