WPF中 INotifyPropertyChanged

在Windows Presentation Foundation (WPF)中,INotifyPropertyChanged 是一个核心接口,用于实现实体类与视图之间的数据双向绑定 。当实体类的某个属性值 发生变化时,通过实现此接口可以立即通知绑定到该属性的所有 UI 控件进行更新,ICommand主要针对的是关联到任何实现了 ICommand 接口的对象的方法。

在C#中,CallerMemberName 是.NET框架提供的一个编译器特性(Compiler Feature),它允许你获取调用当前方法的成员名称,而无需硬编码该名称。这对于实现INotifyPropertyChanged接口特别有用,因为它可以减少手动输入属性名的工作量,提高代码的健壮性和可维护性。

不管是ICommand还是INotifyPropertyChanged 都必须首先将ViewMode的实例设置为控件或整个界面的 DataContext如,this.DataContext = new MainViewModel();DataContext是UI层与数据逻辑层的桥梁。

DataContext作为一个容器,提供了UI层和数据层之间的连接点。在MVVM(Model-View-ViewModel)架构模式中,通常将 ViewModel 设置为控件或整个界面的 DataContext,这样 UI 控件可以通过绑定直接访问 ViewModel 中的数据和命令。

例如,在上面的INotifyPropertyChanged实现中,我们可以使用CallerMemberName特性来简化OnPropertyChanged方法的调用:

cs 复制代码
1using System.ComponentModel;
2using System.Runtime.CompilerServices;
3
4public class MyViewModel : INotifyPropertyChanged
5{
6    // ...
7
8    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
9    {
10        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
11    }
12}
13
14public string MyProperty
15{
16    get { return myPropertyBackingField; }
17    set
18    {
19        if (myPropertyBackingField != value)
20        {
21            myPropertyBackingField = value;
22            OnPropertyChanged(); // 这里不再需要传入 "MyProperty"
23        }
24    }
25}

在此版本中,当你调用OnPropertyChanged()时,编译器会自动填充propertyName参数,将其设为调用方法的成员名称,即"MyProperty"。这样,当MyProperty的值改变时,绑定系统能够准确地知道哪个属性发生了变化并作出相应的更新。

cs 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WpfApplication1
{
    public class MyNotifyProperyChanged : INotifyPropertyChanged //主要通过实现INotifyPropertyChanged接口,实现UI和属性绑定
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string propertyname ="")//属性值变化调用事件,属性特性要调用的属性值给propertyname
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyname));
        }

    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace WpfApplication1
{
    public class MainViewModel : MyNotifyProperyChanged
    {
        public MyCommand MyCommandOrder { get; set; }

        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged();//调用基类事件
            }
        }

        private string _tittle;

        public string Tittle
        {
            get { return _tittle; }
            set { _tittle = value; OnPropertyChanged(); }
        }
        public MainViewModel()
        {
            MyCommandOrder = new MyCommand(ShowMessage);
        }

        public void ShowMessage()
        {
            Name = "点击了按钮";
            Tittle = "我是标题";
            MessageBox.Show(Name);
        }
    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainViewModel();
        }
    }
}
XML 复制代码
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <TextBox  Text="{Binding Name}"> </TextBox>
            <TextBox  Text="{Binding Tittle}" ></TextBox>
            <Button Content="按钮" Command="{Binding MyCommandOrder}"></Button> <!--  Command命令绑定,绑定的也是一个属性,需要指定数据源,实现ICommand接口 -->
        </StackPanel>
    </Grid>
</Window>
相关推荐
c#上位机1 天前
wpf之RelativeSource用法总结
c#·wpf
玖笙&4 天前
✨WPF编程基础【2.1】布局原则
c++·wpf·visual studio
玖笙&4 天前
✨WPF编程基础【2.2】:布局面板实战
c++·wpf·visual studio
SEO-狼术4 天前
.NET WPF 数据编辑器集合提供列表框控件
.net·wpf
FuckPatience8 天前
WPF 具有跨线程功能的UI元素
wpf
诗仙&李白8 天前
HEFrame.WpfUI :一个现代化的 开源 WPF UI库
ui·开源·wpf
He BianGu8 天前
【笔记】在WPF中Binding里的详细功能介绍
笔记·wpf
He BianGu8 天前
【笔记】在WPF中 BulletDecorator 的功能、使用方式并对比 HeaderedContentControl 与常见 Panel 布局的区别
笔记·wpf
123梦野9 天前
WPF——效果和可视化对象
wpf
He BianGu9 天前
【笔记】在WPF中Decorator是什么以及何时优先考虑 Decorator 派生类
笔记·wpf