WPF Master-Details 视图与列表框和组合框与绑定
Posted
技术标签:
【中文标题】WPF Master-Details 视图与列表框和组合框与绑定【英文标题】:WPF Master-Details view with Listbox and Combobox with Binding 【发布时间】:2010-11-15 22:29:59 【问题描述】:几天来,我一直在寻找问题的答案,但找不到解决方案。
问题是组合框用之前选择的用户更新了 User 类中的 Test 对象。
即你选择 user2 并且 user2 有 test2,然后你选择 user5 有 test5。现在如果你再次选择user2,它会显示它有test5。
这是一些代码。我有两个类用户和测试。每个都有两个 ObservableCollections。这就是我设置它们的方式:
public class User
public string Name get; set;
public int test get; set;
public test userTest get; set;
public class test
public int ID get; set;
public String Name get; set;
public class ListOfTests:ObservableCollection<test>
public ListOfTests()
for (int i = 0; i < 4; i++)
test newTest = new test();
newTest.ID = i;
newTest.Name = "Test " + i;
Add(newTest);
public class ListOfUsers: ObservableCollection<User>
public ListOfUsers()
ListOfTests testlist = new ListOfTests();
for (int i = 0; i < 10; i++)
User newUser = new User();
newUser.Name = "User " + i;
newUser.ID = i;
newUser.userTest = testlist[i];
Add(newUser);
XAML 是:
<Window x:Class="ComboboxTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ComboboxTest"
Title="Window1" Height="300" Width="300">
<StackPanel x:Name="SP1">
<StackPanel.Resources>
<local:ListOfTests x:Key="ListOfTests" />
</StackPanel.Resources>
<ListBox ItemsSource="Binding" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="True"/>
<TextBox Text="Binding Path=Name" Foreground="Black" />
<TextBox Text="Binding Path=userTest" />
<ComboBox SelectedItem="Binding Path=userTest"
SelectedValue="Binding Path=userTest.ID"
ItemsSource="Binding Source=StaticResource ListOfTests"
DisplayMemberPath="Name"
SelectedValuePath="ID"
Foreground="Black" />
</StackPanel>
现在,如果我将 SelectedItem 上的绑定更改为“Binding Path=userTest, Mode=OneWay”,那么它可以工作,但我无法手动更改它。
这是一个有趣的想法...如果我以 .Net 4.0 (VS2010) 为目标,那么它可以正常工作...
谁能帮我解决这个问题?
【问题讨论】:
【参考方案1】:如果我理解您的问题,听起来 WPF 在属性值更改时不会收到通知。你可以通过实现INotifyPropertyChanged 接口来解决这个问题。例如,User
类看起来像这样:
public class User : INotifyPropertyChanged
private string name = string.Empty;
public string Name
get return this.name;
set
this.name = value;
this.OnPropertyChanged("Name");
private int test = 0;
public int Test
get return this.test;
set
this.test = value;
this.OnPropertyChanged("Test");
private test userTest = null;
public test UserTest
get return this.userTest;
set
this.userTest = value;
this.OnPropertyChanged("UserTest");
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
PropertyChangedEventHandler eh = this.PropertyChangd;
if(null != eh)
eh(this, new PropertyChangedEventArgs(propName));
您可能也应该为您的 test
课程做同样的事情。
WPF 将监视 PropertyChanged
事件何时触发,并根据需要更新任何受影响的绑定。这应该会导致 ComboBox
中的选定项目更改回 user2 的测试。
更新:好的,我想我已经成功了。我认为您在发布的内容中遗漏了部分代码(例如Window
的DataContext
是什么),但这是我的工作:
我创建了一个名为ViewModel
的类,它设置为主Window
的DataContext
。这是它的代码:
class ViewModel : INotifyPropertyChanged
public ViewModel()
for(int i = 0; i < 4; i++)
this.tests.Add(new Test()
ID = i,
Name = "Test " + i.ToString(),
);
for(int i = 0; i < 4; i++)
this.users.Add(new User()
Name = "User " + i.ToString(),
ID = i,
UserTest = this.tests[i],
);
private ObservableCollection<User> users = new ObservableCollection<User>();
public IEnumerable<User> Users
get return this.users;
private ObservableCollection<Test> tests = new ObservableCollection<Test>();
public IEnumerable<Test> Tests
get return this.tests;
private User currentUser = null;
public User CurrentUser
get return this.currentUser;
set
this.currentUser = value;
this.OnPropertyChanged("CurrentUser");
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
var eh = this.PropertyChanged;
if(null != eh)
eh(this, new PropertyChangedEventArgs(propName));
我将这两个列表的创建移到了代码中。我在您的示例中注意到的一件事是ListOfTests
的一个实例用作ComboBox
的ItemsSource
,而另一个实例用于构建ListOfUsers
。我不确定这是否是问题的一部分,但最好只列出一份测试。
主要Window
的 XAML 如下:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<StackPanel>
<ListBox ItemsSource="Binding Path=Users"
SelectedItem="Binding Path=CurrentUser"
DisplayMemberPath="Name"
IsSynchronizedWithCurrentItem="True">
</ListBox>
<TextBox Text="Binding Path=CurrentUser.Name" />
<TextBox Text="Binding Path=CurrentUser.UserTest.Name" />
<ComboBox ItemsSource="Binding Path=Tests"
SelectedItem="Binding Path=CurrentUser.UserTest"
DisplayMemberPath="Name" />
</StackPanel>
</Window>
让事情顺利进行的关键是CurrentUser
属性。它绑定到ListBox.SelectedItem
,而ComboBox.SelectedItem
绑定到CurrentUser.UserTest
。这将更改ComboBox
中的选择以代表ListBox
中选择的用户的测试。
我使用 Visual Studio 2008 SP1 完成了这一切,因此希望它也适用于您。如果您在执行此操作时遇到任何问题,请告诉我,我会看看我能做些什么。
【讨论】:
嗨安迪,我已经按照你的建议实施了 INotifyPropertyChanged,但不幸的是我仍然遇到同样的问题。我在cid-eddcda42d46afe81.skydrive.live.com/self.aspx/Public%20Dev/… 发布了一个解决方案文件,注意用户编号和测试编号应该相同。随机点击几个用户,然后检查你点击的用户,如果用户和测试仍然排队。 我无法打开您的 zip 文件 - 我收到一条错误消息,指出它无效。无论如何,作为您的 DataContext 并具有 userTest 属性的对象是否也实现了 INotifyPropertyChanged? 嗨,安迪,是的……我有它: public class User : INotifyPropertyChanged private string name; public string Name ... ...私有测试userTest;公共测试用户测试 获取 返回用户测试; 设置 用户测试 = 值; OnPropertyChanged("UserTest"); 哇,这真的很奇怪 - 看起来它应该可以工作。如果今晚或明天有时间,我会尝试用你的代码构建一个示例,看看我是否能解决任何问题。 是的,这很奇怪。我认为这可能是.Net 3.5 SP1 中的一个错误。正如我之前所说,如果我以 .NET 4.0 为目标,它可以正常工作...【参考方案2】:安迪,
这是我现在拥有的代码中更易读的摘录。
public class User : INotifyPropertyChanged
private string name;
public string Name
get
return name;
set
name = value;
OnPropertyChanged("Name");
private int iD;
public int ID
get
return iD;
set
iD = value;
OnPropertyChanged("ID");
private test userTest;
public test UserTest
get
return userTest;
set
userTest = value;
OnPropertyChanged("UserTest");
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
PropertyChangedEventHandler eh = this.PropertyChanged;
if (null != eh)
eh(this, new PropertyChangedEventArgs(propName));
看起来比 cmets 更好。
问候 角
【讨论】:
以上是关于WPF Master-Details 视图与列表框和组合框与绑定的主要内容,如果未能解决你的问题,请参考以下文章
WPF 列表框 + 绑定 + IDataErrorInfo =?
2022-03-23 WPF面试题 ListBox 与 ListView - 如何选择以及何时进行数据绑定?