为什么上涨INotifypPropertyChanged
对于 List<T>
属性不起作用?
考虑这个 MCVE:
public class NotifyPropertyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string property = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
public class TextWrapper
{
public string Text { get; set; }
public override string ToString() => Text;
}
public class ViewModel : NotifyPropertyChanged
{
public List<string> List { get; } = new List<string>();
public TextWrapper Text { get; } = new TextWrapper();
public void AddToList(string text)
{
List.Add(text);
OnPropertyChanged(nameof(List));
}
public void ChangeText(string text)
{
Text.Text = text;
OnPropertyChanged(nameof(Text));
}
}
public partial class MainWindow : Window
{
readonly ViewModel _vm = new ViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = _vm;
}
}
xaml:
<TextBlock Text="{Binding Text}" />
<ListBox ItemsSource="{Binding List}" />
调用 _vm.ChangeText(...)
将正确更新TextBlock
, 同时调用 _vm.AddToList(...)
不更新 ListBox
(它将保持为空)。为什么?
请注意:我知道 ObservableCollection<T>
我知道两种可能的解决方法(将 setter 添加到 List
并将其设置为例如 null
然后返回或更改 DataContext
/ItemsSource
)。我只是好奇屋檐下的东西是什么List<T>
比 TextWrapper
更特别.
最佳答案
当 WPF 绑定(bind)处理 PropertyChanged
事件时,它不会更新其目标属性,除非它产生的有效值实际发生了变化。
因此,除非 List
属性值实际发生变化(添加元素时它不会发生变化),否则调用
OnPropertyChanged(nameof(List));
没有效果。
替换
public List<string> List { get; } = new List<string>();
由
public ObservableCollection<string> List { get; } = new ObservableCollection<string>();
然后像这样编写 AddToList
方法:
public void AddToList(string text)
{
List.Add(text);
}
对于您的 TextWrapper 类:由于您直接绑定(bind)到 TextWrapper 实例,因此 Binding 会调用其覆盖的 ToString()
方法,因此每当 TextWrapper 的 Text
时都会产生不同的值属性已更改。
关于c# - 为什么 List<T> 属性的通知不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43843174/