ListView 未更新项目源 ObservableCollection 项目 属性 更改
ListView not updating on the itemsource ObservableCollection Item Property change
考虑以下示例代码:
View.xml
<Grid>
<ListView Name="NameList" HorizontalAlignment="Left" Height="142" Margin="55,45,0,0" VerticalAlignment="Top" Width="389">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding FirstName}"/>
<Label Content="{Binding LastName}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="Button" HorizontalAlignment="Left" Margin="120,256,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
View.xml.cs
public partial class MainWindow : Window
{
ViewModel vm;
public MainWindow()
{
InitializeComponent();
vm = new ViewModel();
this.DataContext = vm;
NameList.ItemsSource = vm.fn;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
vm.fn.Add(new fullname("P", "Q"));
vm.fn[0].FirstName = "NewName";
}
}
ViewModel.cs
class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
fn = new ObservableCollection<fullname>();
fn.CollectionChanged += ContentCollectionChanged;
fn.Add(new fullname("A", "B"));
fn.Add(new fullname("C", "D"));
}
public void ContentCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (fullname item in e.OldItems)
{
//Removed items
item.PropertyChanged -= EntityViewModelPropertyChanged;
}
}
else if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (fullname item in e.NewItems)
{
//Added items
item.PropertyChanged += EntityViewModelPropertyChanged;
}
}
}
public void EntityViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
//This will get called when the property of an object inside the collection changes
}
public ObservableCollection<fullname> _fn;
public ObservableCollection<fullname> fn
{
get { return _fn; }
set { _fn = value; OnPropertyChanged("fn"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
}
}
}
Model.cs
class fullname : INotifyPropertyChanged
{
public fullname(string f, string l)
{
FirstName = f;
LastName = l;
}
public string _FirstName;
public string FirstName
{
get { return _FirstName; }
set { _FirstName = value; OnPropertyChanged("FirstName"); }
}
public string _LastName;
public string LastName
{
get { return _LastName; }
set { _LastName = value; OnPropertyChanged("LastName"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
}
}
}
如果我在 ObservableCollection 中添加或删除任何项目,它会正确更新视图中的 ListView,但问题是,如果我修改 ObservableCollection 项目 属性,ListView 不会更新。
例如:
单击上面指定的按钮它
一个。添加一个新项目(成功反映在 ListView 中)
b.修改第一项的名字(未反映在 ListView 中)
我应该怎么做才能使修改反映在视图中。
如果有人能指出我做错了什么,我将不胜感激。
ObservableCollection 事件不会在更改项目时触发,仅在添加、删除或移动时触发。
您必须在项目 class 中实现 INotifyPropertyChanged 接口,并在集合中注册每个项目事件。
见here
如果你对合集进行了较大改动,可以提出一个
NotifyCollectionChangedAction.Reset
重置它们的事件
见here
我也在 ListView
和 ObservableCollection
的 WinUI 上遇到同样的问题。
你需要明白的是ObservableCollection
只负责通知集合变化。项目等级变化通过 INotifyPropertyChanged
处理。但是,对于那些要应用的,您需要确保您的绑定模式至少是一种方式,如果需要,则为两种方式。
您的 XAML 应如下所示:
Text="{x:Bind Title, Mode=OneWay}
不要尝试那里提出的建议,这是错误的:
ObservableCollection not noticing when Item in it changes (even with INotifyPropertyChanged)
考虑以下示例代码:
View.xml
<Grid>
<ListView Name="NameList" HorizontalAlignment="Left" Height="142" Margin="55,45,0,0" VerticalAlignment="Top" Width="389">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding FirstName}"/>
<Label Content="{Binding LastName}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="Button" HorizontalAlignment="Left" Margin="120,256,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
View.xml.cs
public partial class MainWindow : Window
{
ViewModel vm;
public MainWindow()
{
InitializeComponent();
vm = new ViewModel();
this.DataContext = vm;
NameList.ItemsSource = vm.fn;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
vm.fn.Add(new fullname("P", "Q"));
vm.fn[0].FirstName = "NewName";
}
}
ViewModel.cs
class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
fn = new ObservableCollection<fullname>();
fn.CollectionChanged += ContentCollectionChanged;
fn.Add(new fullname("A", "B"));
fn.Add(new fullname("C", "D"));
}
public void ContentCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (fullname item in e.OldItems)
{
//Removed items
item.PropertyChanged -= EntityViewModelPropertyChanged;
}
}
else if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (fullname item in e.NewItems)
{
//Added items
item.PropertyChanged += EntityViewModelPropertyChanged;
}
}
}
public void EntityViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
//This will get called when the property of an object inside the collection changes
}
public ObservableCollection<fullname> _fn;
public ObservableCollection<fullname> fn
{
get { return _fn; }
set { _fn = value; OnPropertyChanged("fn"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
}
}
}
Model.cs
class fullname : INotifyPropertyChanged
{
public fullname(string f, string l)
{
FirstName = f;
LastName = l;
}
public string _FirstName;
public string FirstName
{
get { return _FirstName; }
set { _FirstName = value; OnPropertyChanged("FirstName"); }
}
public string _LastName;
public string LastName
{
get { return _LastName; }
set { _LastName = value; OnPropertyChanged("LastName"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
}
}
}
如果我在 ObservableCollection 中添加或删除任何项目,它会正确更新视图中的 ListView,但问题是,如果我修改 ObservableCollection 项目 属性,ListView 不会更新。
例如:
单击上面指定的按钮它
一个。添加一个新项目(成功反映在 ListView 中)
b.修改第一项的名字(未反映在 ListView 中)
我应该怎么做才能使修改反映在视图中。
如果有人能指出我做错了什么,我将不胜感激。
ObservableCollection 事件不会在更改项目时触发,仅在添加、删除或移动时触发。 您必须在项目 class 中实现 INotifyPropertyChanged 接口,并在集合中注册每个项目事件。
见here
如果你对合集进行了较大改动,可以提出一个
NotifyCollectionChangedAction.Reset
重置它们的事件
见here
我也在 ListView
和 ObservableCollection
的 WinUI 上遇到同样的问题。
你需要明白的是ObservableCollection
只负责通知集合变化。项目等级变化通过 INotifyPropertyChanged
处理。但是,对于那些要应用的,您需要确保您的绑定模式至少是一种方式,如果需要,则为两种方式。
您的 XAML 应如下所示:
Text="{x:Bind Title, Mode=OneWay}
不要尝试那里提出的建议,这是错误的: ObservableCollection not noticing when Item in it changes (even with INotifyPropertyChanged)