我意识到这是一个很长的问题,但我发现这里没有别的办法,只能发布我的代码,为了清晰起见,我尽量保持简短。当然,违反了大量的最佳实践,这个例子足够长,因为它是......
我制作了一个非常简单的wpf应用程序
在以下示例中,我编辑了Bar的年龄。但是,在列表中,年龄不会更新。如果我询问基础集合,它似乎仍然有更新.. 如何知道清单?
以下是截图,代码和XAML
注意:如果图像未显示,请尝试在新选项卡或窗口中打开它。
namespace ASAPBinding
{
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
return String.Format("{0} ({1})",Name,Age);
}
}
}
namespace ASAPBinding
{
public class Dal
{
public ObservableCollection<Person> Persons { get; set; }
public Dal()
{
Persons = new ObservableCollection<Person>();
Persons.Add(new Person() {Name = "Bar", Age = 25});
Persons.Add(new Person() {Name = "Foo", Age = 50});
}
public void PrintOutCollection()
{
MessageBox.Show(
Persons[0].ToString() + "\n" + Persons[1].ToString()
);
}
}
}
<Window x:Class="ASAPBinding.EditPersons"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ASAPBinding"
x:Name="window1"
Title="EditPersons" Height="300" Width="300">
<Window.Resources>
<local:Dal x:Key="dal"/>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<ListBox Name="ListBox1"
ItemsSource="{Binding Source={StaticResource dal}, Path=Persons, Mode=TwoWay}"
Grid.Column="0"/>
<StackPanel
DataContext="{Binding ElementName=ListBox1, Path=SelectedItem, Mode=TwoWay}"
Grid.Column="1" Margin="0,0,0,108">
<TextBox Text="{Binding Path=Name}" />
<TextBox Text="{Binding Path=Age}" />
<Button Click="Button_Click">Show Collection</Button>
</StackPanel>
</Grid>
</Window>
public partial class EditPersons : Window
{
public EditPersons()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Dal dal = (Dal) window1.FindResource("dal");
dal.PrintOutCollection();
}
}
答案 0 :(得分:5)
拥有ObservableCollection是不够的,如果要更新特定属性的绑定,您的Person类型必须实现INotifyPropertyChanged。
修改
我刚注意到,您的左侧ListBox未更新,因为您没有为Person对象设置DataTemplate。你现在拥有的是一个ToString()实现,它一旦报告给UI就不会得到更新。
你需要这样的东西:
<DataTemplate DataType="{x:Type local:Person}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="("/>
<TextBlock Text="{Binding Age}"/>
<TextBlock Text=")"/>
</StackPanel>
</DataTemplate>
答案 1 :(得分:2)
首先,在收集级别,您ItemsSource
的{{1}}应为ListView
ObservableCollection
这将通知ObservableCollection<Person> Persons = new ObservableCollection<Person>();
项目的顺序已更改。
其次,在项目级别。您ListView
也应该按照官方document和here中的说明实施Person
界面。
这将告诉INotifyPropertyChanged
项目的内容已被更改。
实施ListView
时,
INotifyPropertyChanged
已定义,必须在属性设置器中名为显式。
需要注意的一点是,您不需要对属性名称进行硬编码,public event PropertyChangedEventHandler PropertyChanged;
属性可用于自动获取调用者的名称。
CallerMemberName
答案 2 :(得分:1)
示例:
public class Person : DependencyObject
{
public static readonly DependencyProperty NameProperty = DependencyProperty.Register(
"Name",
typeof(string),
typeof(Person)
);
public static readonly DependencyProperty AgeProperty = DependencyProperty.Register(
"Age",
typeof(int),
typeof(Person)
);
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
public int Age
{
get { return (int)GetValue(AgeProperty ); }
set { SetValue(AgeProperty , value); }
}
public override string ToString()
{
return String.Format("{0} ({1})",Name,Age);
}
}