Cor*_*ger 3 data-binding wpf combobox listbox
我几天来一直在四处寻找我的问题的答案,但我找不到解决方案.
问题是组合框用以前选择的用户'更新User类中的Test对象.
即,您选择user2,user2具有test2,然后选择具有test5的user5.现在,如果再次选择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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
而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>
Run Code Online (Sandbox Code Playgroud)
现在,如果我将SelectedItem上的Binding更改为"{Binding Path = userTest,Mode = OneWay}",那么它可以工作,但我无法手动更改它.
这是一个踢球者的想法......如果我的目标是.Net 4.0(VS2010),那么它的工作正常......
有人可以帮我找到解决方案吗?
如果我理解你的问题,听起来好像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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
您也应该为您的test班级做同样的事情.
WPF将监视PropertyChanged事件何时触发,并根据需要更新任何受影响的绑定.这应该导致所选项目ComboBox更改回user2的测试.
更新:好的,我想我有这个工作.我认为你缺少的部分代码在你发布的内容(像什么DataContext的Window啦),但这里是我得到的工作:
我创建了一个名为的类ViewModel,它被设置为DataContextmain Window.这是它的代码:
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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
我将两个列表的创建移动到代码中.有一件事我你的样品中注意到的是,一个实例ListOfTests被用作ItemsSource的ComboBox,而另一个实例是用来建造ListOfUsers.我不确定这是否是问题的一部分,但最好只有一个测试列表.
主要的XAML Window如下:
<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>
Run Code Online (Sandbox Code Playgroud)
让事情发挥作用的关键是CurrentUser财产.这势必会ListBox.SelectedItem,并ComboBox.SelectedItem势必CurrentUser.UserTest.这将改变选择,ComboBox以表示在中选择的用户的测试ListBox.
我使用Visual Studio 2008 SP1完成了所有工作,所以希望它也能为您工作.如果您在使用此工作时遇到任何问题,请告诉我,我会看到我能做些什么.