WPF如何在不重置项目的情况下更新绑定列表?
WPF如何在不重置项目的情况下更新绑定列表?
在一个简单的WPF XAML UI中显示了一个项目列表:
窗口x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="450" Width="800">
数据在C#视图模型中:
使用System.ComponentModel;
使用System.Threading.Tasks;
使用System.Windows;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
Items.Add(new MyItem());
Items.Add(new MyItem());
Items.Add(new MyItem());
Items.Add(new MyItem());
Loaded += async (s, e) =>
{
while (true)
{
await Task.Delay(1000); // 可能在此处更改项目
Items.ResetBindings(); // 让UI知道添加/删除/重新排序/修改的项目
}
};
}
public BindingList
}
public class MyItem : INotifyPropertyChanged
{
public string Text { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
项目可以自动更改,因此调用Items.ResetBindings();可以在UI中显示这些更改。但这也会破坏UI:焦点和用户对当前项目的任何修改都会消失!
如何在不重置UI控件的情况下更新绑定列表?
问题出现的原因是在WPF中更新绑定列表时,可能会导致重置项。解决方法是通过正确触发属性更改事件来更新绑定列表,而不是调用Items.ResetBindings()
方法。
具体解决方法如下:
1. 在MyItem类中实现INotifyPropertyChanged接口,确保属性更改时会触发PropertyChanged事件。
2. 在Text属性的set访问器中,添加PropertyChanged事件的触发代码。
3. 在MainWindow类中,不再调用Items.ResetBindings()方法。
4. 在Loaded事件处理程序中,使用异步循环定期添加新的MyItem实例到Items列表,并更新Text属性。
以下是完整的解决方案代码:
public class MyItem : INotifyPropertyChanged { private string _text; public string Text { get { return _text; } set { _text = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text))); } } public event PropertyChangedEventHandler PropertyChanged; } public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = this; Items.Add(new MyItem()); Items.Add(new MyItem()); Items.Add(new MyItem()); Items.Add(new MyItem()); Loaded += async (s, e) => { while (true) { await Task.Delay(1000); Items.Add(new MyItem() { Text = "new" }); } }; } public BindingListItems { get; } = new BindingList (); }
以上解决方案中,我们通过正确地触发属性更改事件来更新绑定列表,而不是调用不必要的ResetBindings方法。这样可以确保将新的MyItem实例添加到Items列表时,UI能够正确地更新,而不会丢失其他状态(如选中项)。