我几天来一直在寻找我的问题的答案,但我找不到解决方案。
问题是组合框用以前选择的用户更新了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);
}
}
}
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更改为“{Binding Path = userTest,Mode = OneWay}”,那么它可以正常工作,但我无法手动更改它。
这是一个踢球者的想法......如果我的目标是.Net 4.0(VS2010),那么它的工作正常......
任何人都可以帮我找到解决方案吗?
答案 0 :(得分:5)
如果我理解你的问题,听起来好像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
中的所选项目更改回用户2的测试。
更新:好的,我认为我的工作正常。我认为你在发布的内容中缺少部分代码(比如DataContext
的{{1}}),但这就是我的工作:
我创建了一个名为Window
的类,该类设置为主ViewModel
的{{1}}。这是它的代码:
DataContext
我将两个列表的创建移到了代码中。我在您的示例中注意到的一件事是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));
}
}
}
的{{1}},而另一个实例用于构建ListOfTests
。我不确定这是否是问题的一部分,但最好只有一个测试列表。
主要ItemsSource
的XAML如下:
ComboBox
让事情有效的关键是ListOfUsers
属性。它绑定到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>
绑定到CurrentUser
。这将更改ListBox.SelectedItem
中的选择,以表示在ComboBox.SelectedItem
中选择的用户的测试。
我使用Visual Studio 2008 SP1完成了所有工作,所以希望它也能为您工作。如果您在使用此工作时遇到任何问题,请告诉我,我会看到我能做些什么。
答案 1 :(得分:0)
安迪,
这是我现在的代码中更易读的摘录。
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));
}
}
}
看起来比评论更好。
此致 Corne