Laden...

WPF - Textbox wird nicht upgedated (OnPropertyChanged)

Erstellt von Leola vor 2 Jahren Letzter Beitrag vor 2 Jahren 298 Views
L
Leola Themenstarter:in
3 Beiträge seit 2020
vor 2 Jahren
WPF - Textbox wird nicht upgedated (OnPropertyChanged)

Hallo zusammen,

ich hänge an einem trivialem Problem:

Ich habe eine Combobox mit zwei Werten, je nach Auswahl werden zwei Textboxen upgedated. Das funktioniert auch, wenn man sich die Propertys danach ansieht, nur die Änderung kommt im View nicht an.

Mein Modell (Alles stark vereinfacht):


public class Settings
    {
        public double Wert1 { get; set; }
        public double Wert2 { get; set; }
}

Mein Viewmodell:


public class MainVM : INotifyPropertyChanged
    {
        private Settings _Settings;
        public Settings Settings
        {
            get { return _Settings; }
            set
            {
                if (value != null || value != _Settings) _Settings = value;
                OnPropertyChanged("Settings");
            }
        }

private List<string> _ProbeP1Collection;
        public List<string> ProbeP1Collection
        {
            get { return _ProbeP1Collection; }
            set
            {
                if (value != null || value != _ProbeP1Collection) _ProbeP1Collection = value;
                OnPropertyChanged("ProbeP1Collection");               

            }
        }
        public SetP1AlarmCommand SetP1AlarmCommand { get; set; }

       public MainVM()
        {
           SetP1AlarmCommand = new SetP1AlarmCommand(this);
           Settings = new Settings();
           
         ProbeP1Collection = new List<string>()
            {
                "Probe1",
                "Probe2"              
            };      
     
           Settings.Wert1 = 2.4;
           Settings.Wert2 = 10;
         }

//wird von SetP1AlarmCommand SetP1AlarmCommand ausgeführt
public void SetP1Co()
        {
            if (ProbeP1 == "Probe1")
            {
              
                Settings.Wert1 = -13.00;
                Settings.Wert2 = -2.50;
                MessageBox.Show("Probe1: " + Settings.Wert1.ToString() + "Lower: " + Settings.Wert2.ToString());

            } else if (ProbeP1 == "Probe2")
            {
                
                Settings.Wert1 = -18.00;
                Settings.Wert2 = -3.00;
                MessageBox.Show("Probe2: " + Settings.Wert1 + "Lower: " + Settings.Wert2.ToString());

            } else
            {
                Settings.Wert1 = -13.00;
                Settings.Wert2 = -2.50;
            }             
        }
}

Ja, und natürlich gibts auch einen View dazu, hier die relevanten parts:


<ComboBox  IsEditable="false" Height="24" Width="229"
                                          ItemsSource="{Binding ProbeP1Collection, Mode=OneWay}"                                         
                                          SelectedItem="{Binding ProbeP1, Mode=OneWayToSource}">                                            
                                            <i:Interaction.Triggers>
                                                <i:EventTrigger EventName="SelectionChanged" SourceObject="{Binding ElementName=comboP1}">
                                                    <i:InvokeCommandAction Command="{Binding SetP1AlarmCommand}" />
                                                </i:EventTrigger>
                                            </i:Interaction.Triggers>
                                        </ComboBox>

<TextBox Width="90px" Style="{StaticResource number}" Text="{Binding Settings.Wert1, Mode=TwoWay, StringFormat=\{0:F2\}}"/>
<TextBox Width="90px" Style="{StaticResource number}" Text="{Binding Settings.Wert2, Mode=TwoWay, StringFormat=\{0:F2\}}"/>


Wenn ich Wert1 direkt im Viewmodel als Property setze geht es natürlich. Aber ich möchte ja das Modell nutzen, und nicht 30 Propertys im VM anlegen. Wenn ich zwei Textboxen mit Binding Wert1 anlege und in einer was ändere wird der View ja auch aktualisiert, wieso klappt das nicht über die Combobox?

Wäre sehr dankbar für einen Input, Brett vorm Kopf momentan...

LG Bettina

4.931 Beiträge seit 2008
vor 2 Jahren

Hallo,

der Setter für Settings wird nur aufgerufen, wenn du direkt dieses Objekt änderst und nicht bei Änderungen einer der Eigenschaften davon.
Dir bleibt nicht anderes übrig, als explizit dafür VM-Eigenschaften zu erstellen (oder aber direkt für deine Settings-Klasse INotifyPropertyChanged zu implementieren und für alle Setter der Eigenschaften OnPropertyChanged(...) aufzurufen).

Es gibt aber bessere Möglichkeiten als explizit OnPropertyChanged mit festen String-Literalen aufzurufen, z.B. mit nameof(...) oder mittels des CallerMemberName-Attributes, s. z.B. Use CallerMemberName Attribute to Make INotifyPropertyChanged Implementation Cleaner.

Und es gibt einer Reihe von Libs, welche das Erzeugen der Setter automatisieren, z.B. PropertyChanged.Fody, KindOfMagic oder Assisticant.

309 Beiträge seit 2020
vor 2 Jahren

Du kannst auch nach der Änderung OnPropertyChanged feuern. Am saubersten wäre aber wahrscheinlich Settings als eigenes ViewModel.
Je nachdem wie groß das ganze wird oder nach Quelle könntest du das original Objekt dann mittels AutoMapper in ein ViewModel umwandeln.


MyNewCommand = new RelayCommand(parameter => {

        Settings.Wert1 = 100;
        OnPropertyChanged(nameof(Settings));
    },
    parameter => true
);

L
Leola Themenstarter:in
3 Beiträge seit 2020
vor 2 Jahren

Danke, jetzt funktioniert es natürlich! Auf die schnelle im Model INotifyPropertyChanged implementiert, das ging sofort (Aber das ist nicht sauber glaube ich, sollte man ja eigentlich nicht im Model oder?)

Ich teste auch die anderen Möglichkeiten, das mit den verschiedenen Viewmodels versuche ich gerade parallel in einem anderen Projekt mittels Caliburn umzusetzen, erscheint mir bei weitem die eleganteste Möglichkeit.

Liebe Grüße und danke für den wertvollen Input!
Bettina