Wieso funktioniert meine WPF-Bindung zwischen Textbox und Property nicht?
Hi Leute,
ich möchte eine Bindung erzeugen.
Es gibt eine Textbox in der man etwas eingeben kann. Die Änderungen in der Textbox sollen in eine Property einer Model-Klasse geschrieben werden per Binding.
Die Property ist wiederum an die TextProperty eines Labels gebunden (Es soll so gemacht werden laut Aufgabenstellung).
Trotz meiner Bindungen aktualisiert sich das Label nicht wenn ich etwas in der TextBox eingebe.
Hier der Code aus dem Code-Behind. Die Komponenten wie Textbox, Label sind im XAML angelegt.
Student marco = new Student("Max", "Mustermann", 12345689);
Binding myBinding = new Binding(nameof(marco.Matrikelnummer));
myBinding.Source = marco;
myBinding.Mode = BindingMode.TwoWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
studentAnzeige.SetBinding(Label.ContentProperty, myBinding);
Binding second = new Binding(nameof(marco.Matrikelnummer));
second.Source = marco;
second.Mode = BindingMode.TwoWay;
second.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
tb1.SetBinding(TextBox.TextProperty, second);
Kann mir jemand weiterhelfen?
1 Antwort
Wieso nimmst du das Binding im Code vor und nicht in der XAML-View?
Die View könnte so aussehen (die hierfür irrelevanten Attribute lasse ich einmal weg):
<Window xmlns:local="clr-namespace:ExampleProject">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<StackPanel>
<TextBox Text="{Binding LabelContent, UpdateSourceTrigger=PropertyChanged}" />
<Label Content="{Binding LabelContent}" />
</StackPanel>
</Window>
Wichtig ist hier zum Einen, dass der Datenkontext auf der ViewModel-Klasse liegt und zum anderen der UpdateSourceTrigger auf PropertyChanged.
Im ViewModel muss das Property (ich habe es für die Demonstration LabelContent genannt) bei Änderung ein PropertyChanged-Event werfen.
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace ExampleProject
{
public class ViewModel : INotifyPropertyChanged
{
private string _labelContent;
public string LabelContent
{
get => _labelContent;
set
{
if (_labelContent != value)
{
_labelContent = value;
OnPropertyChanged(nameof(LabelContent));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
Beides lässt sich aus dem obigen Text nicht herleiten. Aber es funktioniert ebenso:
1) Das View (wieder nur der relevante Teil):
<StackPanel>
<TextBox x:Name="tb1" />
<Label x:Name="studentAnzeige" />
</StackPanel>
2) Der Konstruktor in der xaml.cs (ich diesmal mal einfach das ViewModel weg):
InitializeComponent();
// your code ...
An deinem Code braucht keine Anpassung für die Funktionalität vorgenommen werden.
3) Die Student-Klasse:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace ExampleProject
{
public class Student : INotifyPropertyChanged
{
private int _matriculationNumber;
public Student(string firstname, string lastname, int matriculationNumber)
{
// ...
}
public int Matrikelnummer
{
get => _matriculationNumber;
set
{
if (_matriculationNumber != value)
{
_matriculationNumber = value;
OnPropertyChanged(nameof(Matrikelnummer));
}
}
}
// property changed implementation ...
}
}
Den Namen des Properties würde ich noch anpassen (einen englischen Bezeichner verwenden).
Naja, das besagt die Aufgabenstellung, das ich diese Bindung im Code-Behind machen soll. Es ist eine Aufgabe von meinem Lehrer. Aber die Schritte, die du zeigst, habe ich doch eigentlich auch gemacht? Also ich habe bei meiner Property INotifyPropertyChanged implementiert.