WPF - 002 数据更新
数据更新
数据绑定不仅可以绑定现有的控件属性,也可以绑定自定义类的属性,通过 INotifyPropertyChanged
接口实现绑定源到绑定目标的消息通知。
非列表属性的更新
例如:以下代码通过定义一个 User
类,并将其中的 Name
属性绑定至 TextBox
的 Text
属性上,为了实现后台属性更新时对前台UI的通知,User
类需要实现 INotifyPropertyChanged
接口,并在属性的 Setter
中调用 OnPropertyChanged
函数,触发属性更改事件。
后台代码:
/// <summary>
/// DataUpdateDemo1.xaml 的交互逻辑
/// </summary>
public partial class DataUpdateDemo1 : Window
{
User user = new User();
public DataUpdateDemo1()
{
InitializeComponent();
user.Name = "Gerry";
// 指定窗口的 DataContext 属性
this.DataContext = user;
}
private void BtnUpdateSource_Click(object sender, RoutedEventArgs e)
{
this.user.Name = "Update UserInfo";
}
}
/// <summary>
/// 创建 User 类
/// </summary>
public class User : INotifyPropertyChanged
{
private string? _name;
public string? Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(nameof(Name)); }
}
public event PropertyChangedEventHandler? PropertyChanged;
/// <summary>
/// 当指定的某个属性发生变化的时候对界面UI的线程推送更新消息
/// </summary>
/// <param name="PropertyName"></param>
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
前台代码:
<StackPanel Margin="20">
<TextBox Width="150" Text="{Binding Name}"></TextBox>
<Button Margin="0 10 0 0" Content="更新源" Name="BtnUpdateSource" Click="BtnUpdateSource_Click" Width="150"></Button>
</StackPanel>
列表属性的更新
ItemControl
类的 DisplayMemberPath
属性可以指定需要绑定的列表内的对象的属性。例如:使用 ListBox
显示用户信息,ListBox
的 ItemSource
指定关联到列表框的用户信息集合,DisplayMemberPath
指定需要显示的用户信息对象的属性。
此时需要使用 ObservableCollection
类初始化一个 UserInfo
对象列表,ObservableCollection
内部已经实现了 INotifyPropertyChanged
接口,因此对列表框内的用户信息对象进行删除和添加可以反馈到 UI 界面,但是对用户信息的修改无法反馈至 UI,这是由于对列表框的用户信息对象的属性进行更改不会造成对象引用的变更,因此无法反馈至UI界面。为了实现对象属性变更对前台UI的通知,需要对 UserInfo
类也实现 INotifyPropertyChanged
接口。
/// <summary>
/// DataUpdateDemo2.xaml 的交互逻辑
/// </summary>
public partial class DataUpdateDemo2 : Window
{
private ObservableCollection<UserInfo> users = new ObservableCollection<UserInfo>();
public DataUpdateDemo2()
{
InitializeComponent();
// 初始化集合中的元素
InitialzedUsers();
// 绑定到用户集合列表框
lbUsers.ItemsSource = users;
}
private void InitialzedUsers()
{
users.Add(new UserInfo { Name = ".NET Core"});
users.Add(new UserInfo { Name = ".NET Framework"});
}
private void BtnAdd_Click(object sender, RoutedEventArgs e)
{
users.Add(new UserInfo { Name = "Python" });
}
private void BtnUpdate_Click(object sender, RoutedEventArgs e)
{
if (lbUsers.SelectedItem != null)
{
(lbUsers.SelectedItem as UserInfo)!.Name = "Golang";
}
}
private void BtnDelete_Click(object sender, RoutedEventArgs e)
{
if (lbUsers.SelectedItem != null)
{
users.Remove((lbUsers.SelectedItem as UserInfo)!);
}
}
}
public class UserInfo : INotifyPropertyChanged
{
private string? _name;
public string? Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(nameof(Name)); }
}
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}