将UI值绑定到WPF中模型的对象实例
我有一个简单的wpf项目,它包含一个包含Employees的ObservableCollection和3个文本框的列表框。将UI值绑定到WPF中模型的对象实例
我做了一个“模型”类,以及将像Employee这样的属性对象链接到MainWindow。 Employee类的属性称为“CurrentEmployee”。
我将一个Model对象初始化为Window并将其命名为“boundModel”。当选择在列表框上发生变化时,我希望“boundModel.CurrentEmployee”更改为选择哪个员工,并且这3个文本框也要更改为员工的属性。我目前将“boundModel.CurrentEmployee”设置为列表框中选择的任何名称。当列表框选择发生变化时,boundModel.CurrentEmployee!不幸的是,它不会在MainWindow上更新!
我想将boundModel.CurrentEmployee绑定到3个文本框。我想这样做,所以当我创建另一个类时,我可以通过Model类将该类链接到更多的UI控件。这是可能的,还是以任何方式高效?我的Windows窗体背景在这里似乎几乎没用!
提前致谢!
主窗口后端
public partial class MainWindow : Window
{
Model boundModel;
public MainWindow()
{
boundModel = new Model();
InitializeComponent();
this.DataContext = boundModel;
lb_Employees.ItemsSource = boundModel.EmployeeCollection;
}
private void lb_Employees_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
boundModel.CurrentEmployee = (Employee)lb_Employees.SelectedItem;
}
}
主窗口XAML
<ListBox x:Name="lb_Employees" SelectionChanged="lb_Employees_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox x:Name="tb_Name" Text="{Binding boundModel.Name}"/>
<TextBox x:Name="tb_Age" Text="{Binding Age}"/>
<TextBox x:Name="tb_Kids" Text="{Binding HasKids}"/>
雇员
class Employee : System.ComponentModel.INotifyPropertyChanged
{
private string name;
private int age;
private bool hasKids;
public string Name
{
get{return name;}
set
{
name = value;
Notify("Name");
}
}
public int Age
{
get{return age;}
set
{
age = value;
Notify("Age");
}
}
public bool HasKids
{
get{return hasKids;}
set
{
hasKids = value;
Notify("HasKids");
}
}
public Employee(string name, int age, bool haskids)
{
this.Name = name;
this.Age = age;
this.HasKids = haskids;
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
private void Notify(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this,
new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
型号
class Model : System.ComponentModel.INotifyPropertyChanged
{
public ObservableCollection<Employee> EmployeeCollection = new ObservableCollection<Employee>();
private Employee currentemployee;
public Employee CurrentEmployee
{
get {return currentemployee;}
set
{
currentemployee = value;
Notify("Employee");
}
}
public Model()
{
EmployeeCollection.Add(new Employee("Tom Smith", 40, true));
EmployeeCollection.Add(new Employee("Beth Smith", 38, true));
EmployeeCollection.Add(new Employee("Steph Rodriguez", 25, false));
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
private void Notify(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this,
new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
此属性的名称为CurrentEmployee
,不Employee
。
public Employee CurrentEmployee
{
get {return currentemployee;}
set
{
currentemployee = value;
//Notify("Employee");
Notify("CurrentEmployee");
}
}
boundModel
是一个私人领域。你不能绑定到私人的任何东西,你不能绑定到任何类型的领域。
它也是(或应该)与DataContext
相同的对象。这些绑定将转至DataContext
以查找其路径中指定的属性。所以,如果你要绑定到DataContext.CurrentEmployee.Name
,这样做的:
<TextBox x:Name="tb_Name" Text="{Binding CurrentEmployee.Name}"/>
<TextBox x:Name="tb_Age" Text="{Binding CurrentEmployee.Age}"/>
<TextBox x:Name="tb_Kids" Text="{Binding CurrentEmployee.HasKids}"/>
其实我建议摆脱boundModel
,做这个(我不会的名字我的视图模型的模式,但你已经做了):
public MainWindow()
{
InitializeComponent();
ViewModel = new Model();
}
public Model ViewModel {
get { return DataContext as Model; }
set { DataContext = value; }
}
而且我的ItemsSource绑定在XAML,并通过结合以及设置CurrentEmployee:
<ListBox
x:Name="lb_Employees"
ItemsSource="{Binding EmployeeCollection}"
SelectedItem="{Binding CurrentEmployee}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
更新
哎呀,另一种简化的方法:ItemTemplate没有足够的证据来证明它的存在。您可以使用DisplayMemberPath
代替:
<ListBox
x:Name="lb_Employees"
ItemsSource="{Binding EmployeeCollection}"
SelectedItem="{Binding CurrentEmployee}"
DisplayMemberPath="Name"
/>
现在我们已经与所有在代码隐藏直接与视图模型交互的地方的分配,我们可以与ViewModel
财产分配也是如此。它不再需要。 Codebehind不是不好的的事情,但是如果你正确地做了WPF,你经常会发现在那里几乎没有必要做任何事情。
谢谢!这完全按照预期工作。 感谢您的详细解答。你为我节省了几个小时的研究 A + – BG42331