Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
WPF - Textbox wird nicht upgedated (OnPropertyChanged)
Leola
myCSharp.de - Member



Dabei seit:
Beiträge: 3

Themenstarter:

WPF - Textbox wird nicht upgedated (OnPropertyChanged)

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4192

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
JimStark
myCSharp.de - Member

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 297

beantworten | zitieren | melden

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
);
private Nachricht | Beiträge des Benutzers
Leola
myCSharp.de - Member



Dabei seit:
Beiträge: 3

Themenstarter:

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers