2017-10-17 57 views
0

我有一个简单的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)); 
    } 
} 

回答

0

此属性的名称为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,你经常会发现在那里几乎没有必要做任何事情。

+1

谢谢!这完全按照预期工作。 感谢您的详细解答。你为我节省了几个小时的研究 A + – BG42331