在UIF

时间:2017-10-17 16:19:12

标签: c# wpf xaml data-binding listbox

我有一个简单的wpf项目,它包含一个包含Employees的ObservableCollection和3个文本框的列表框。

我做了一个"模型"类以及将Employee等属性对象链接到MainWindow的类。 Employee类的属性称为" CurrentEmployee"。

我将一个Model对象初始化为Window并将其命名为" boundModel"。当在列表框中更改选择时,我想要" boundModel.CurrentEmployee"更改为选择的员工,以及3个文本框也更改为员工的属性。我目前设置" boundModel.CurrentEmployee"在列表框中选择的任何名称。当列表框选择发生变化时,boundModel.CurrentEmployee就变了!不幸的是,它没有在MainWindow上更新!

我想将boundModel.CurrentEmployee绑定到3个文本框。我想这样做,这样当我创建另一个类时,我可以通过Model类将该类链接到更多的UI控件。这是可能的,还是以任何方式有效的?我的窗户形式背景在这里看起来几乎没用!

提前致谢!

主窗口后端

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));
    }
}

1 个答案:

答案 0 :(得分: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并执行此操作(我不会将我的viewmodel模型命名为,但您已经这样做了):

public MainWindow()
{
    InitializeComponent();

    ViewModel = new Model();
}

public Model ViewModel { 
    get { return DataContext as Model; }
    set { DataContext = value; }
}

我将在XAML中绑定ItemsSource,并通过绑定设置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直接交互的所有地方,我们也可以免除ViewModel属性。它不再需要了。 Codebehind不是的东西,但如果你正确地做WPF,你经常会发现那里几乎没有必要做任何事情。