WPF - 002 数据更新

数据更新

数据绑定不仅可以绑定现有的控件属性,也可以绑定自定义类的属性,通过 INotifyPropertyChanged 接口实现绑定源到绑定目标的消息通知。

非列表属性的更新

例如:以下代码通过定义一个 User 类,并将其中的 Name 属性绑定至 TextBoxText 属性上,为了实现后台属性更新时对前台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>

img

列表属性的更新

ItemControl 类的 DisplayMemberPath 属性可以指定需要绑定的列表内的对象的属性。例如:使用 ListBox 显示用户信息,ListBoxItemSource 指定关联到列表框的用户信息集合,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));
        }
    }
}

img

posted @ 2023-07-16 15:18  Snoopy1866  阅读(79)  评论(2编辑  收藏  举报