当集合的属性发生更改(添加/删除列表中的项目工作正常)时,我在更新包含ObservableCollection的Listbox时遇到问题:
列表框已设置ItemsSource="{Binding Path=AllPerson}"
,后面的代码中的数据上下文设置为此this.DataContext = allPersonClass;
。
allPersonClass
包含ObservableCollection<Person> allPerson
类Person
包含名称等属性
我覆盖了人的ToString
方法以返回Name
属性,因此listBox显示有效数据
我尝试Person
实施INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(object sender, string propertyName) {
if (this.PropertyChanged != null) {
PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
}
}
public string Name {
get { return name; }
set {
name = value;
onPropertyChanged(this, "allPersonClass");
}
}
并且在每个属性setter中都有onPropertyChanged(this, "propertyName");
执行但listBox永远不会更新已创建的项
知道可能出现什么问题吗?
这是带有listBox xaml的窗口
<Button x:Name="btnDetail" Content="Detail" HorizontalAlignment="Left" Margin="361,249,0,0" VerticalAlignment="Top" Width="75" Click="ButtonDetailClick"/>
<ListBox x:Name="listPerson" ItemsSource="{Binding Path=AllPerson}" HorizontalAlignment="Left" Height="170" Margin="33,29,0,0" VerticalAlignment="Top" Width="155" IsSynchronizedWithCurrentItem="True"/>
<Button x:Name="btnLoad" Content="Load" HorizontalAlignment="Left" Margin="58,249,0,0" VerticalAlignment="Top" Width="75" Click="btnLoad_Click"/>
<Button x:Name="btnSave" Content="Save" HorizontalAlignment="Left" Margin="138,249,0,0" VerticalAlignment="Top" Width="75" Click="ButtonSaveClick"/>
这是DetailView窗口的一部分,其中进行了修改(绑定到Person)
<TextBox Text="{Binding Path=Name}" Height="23" HorizontalAlignment="Left" Margin="118,20,0,0" Name="txtName" VerticalAlignment="Top" Width="141" />
这里是部分AllPersonClass:
public class AllPersonClass {
private ObservableCollection<Person> allPerson;
public AllPersonClass() {
allPerson = new ObservableCollection<Person>();
}
public ObservableCollection<Person> AllPerson {
get { return allPerson; }
set { allPerson = value; }
}
public void addPerson(Person newPerson) {
allPerson.Add(newPerson);
}
public Person getPerson(int personIndex) {
return allPerson[personIndex];
}
}
修改
这是在详细视图中保存更改的方法的相关部分
private void OnBtnSaveClick(object sender, RoutedEventArgs e) {
person.Name = txtName.Text;
person.SurName = txtSurName.Text;
}
请注意,更改是在'ObservableCollection allPerson'中进行的,只有listBox保持显示旧数据
答案 0 :(得分:10)
如果您希望在更改Person属性时更新UI,则必须通知该属性已更改,而不是类
public string Name
{
get { return name; }
set
{
name = value;
onPropertyChanged(this, "allPersonClass");
}
}
<TextBox Text="{Binding Path=Name}" .....
应该是
public string Name
{
get { return name; }
set
{
name = value;
onPropertyChanged(this, "Name");
}
}
<TextBox Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" .....
您无需覆盖ToString()
模型上的Person
以便在ListBox
中正确显示,您可以设置ListBox
DisplayMemberPath
来显示您想要的属性ListBox
<ListBox ItemsSource="{Binding Path=AllPerson}" DisplayMemberPath="Name" />
编辑:回答您的评论问题:
public string Name
{
get { return name; }
set
{
name = value;
onPropertyChanged(this, "Name");
onPropertyChanged(this, "Display");
}
}
public string Surname
{
get { return surname; }
set
{
surname= value;
onPropertyChanged(this, "Surname");
onPropertyChanged(this, "Display");
}
}
public string Display
{
get { return Name + " " + Surname; }
}
答案 1 :(得分:5)
在DetailView中,您需要定义一个TwoWay-Binding来更新person
类的属性名称。
<TextBox Text="{Binding Path=Name, Mode=TwoWay}" Height="23" HorizontalAlignment="Left" Margin="118,20,0,0" Name="txtName" VerticalAlignment="Top" Width="141" />
此外,如果您想在每次写入文本时更新属性,还需要使用UpdateSourceTrigger
定义PropertyChanged
。否则,属性仅在TextBox失去焦点时才更新。
<TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="23" HorizontalAlignment="Left" Margin="118,20,0,0" Name="txtName" VerticalAlignment="Top" Width="141" />
答案 2 :(得分:4)
您的问题是您的收藏品从未通知您的PropertyChanged
这应该可以帮到你
ObservableCollection<INotifyPropertyChanged> items = new ObservableCollection<INotifyPropertyChanged>();
items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(items_CollectionChanged);
static void items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
foreach (INotifyPropertyChanged item in e.OldItems)
item.PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
foreach (INotifyPropertyChanged item in e.NewItems)
item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
}
static void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
另请参阅此Link
答案 3 :(得分:3)
我想您可能想要查看您在项目级别进行绑定的方式。看看这个链接,它会让你入门:
How to determine if a row in ObservableCollection<T> actually changed