首页 > 解决方案 > 使用 INotifyPropertyChanged 的​​ WPF Xaml 绑定类实例

问题描述

我在使用 XAML 中的数据绑定时遇到问题。问题如下,我想从我的 ExampleClass 的 istance 更新标签。我看到两种方法,但其中一种不起作用。第一个是(在示例代码 label1 中):在您的 xaml.cs 中定义一个属性,该属性是您对 ExampleClass 实例的引用,在您的 xaml 中只需编写 YourPropertyReferenceToExampleClass.PropertyName 但它不起作用第二个很简单(在示例代码 label2 中) ,将您的标签的 dataContext 设置为 ExampleClass 的一个实例,并在您的 xaml 中简单地编写 PropertyName。

下面的代码(Xaml):

<Window x:Class="SimpleBinding.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:SimpleBinding"
    mc:Ignorable="d"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Title="MainWindow" Height="137.03" Width="255.263">
<Grid>
    <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="45,76,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
    <Label x:Name="label" Content="{Binding One}" HorizontalAlignment="Left" Margin="10,14,0,0" VerticalAlignment="Top"/>
    <Label x:Name="label1" Content="{Binding T.Name}" HorizontalAlignment="Left" Margin="10,45,0,0" VerticalAlignment="Top"/>
    <Label x:Name="label2" Content="{Binding Name}" HorizontalAlignment="Left" Margin="10,45,0,0" VerticalAlignment="Top"/>

</Grid>

在代码 (Xaml.cs) 下方:

using System.ComponentModel;
using System.Windows;

namespace SimpleBinding
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private string _one;
        public string One
        {
            get => _one; set
            {
                _one = value;
                OnPropertyChanged("One");
            }
        }

        public ExampleClass T { get; private set; }

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            One = "ciao";
            T = new ExampleClass();
            label2.DataContext = T;
            T.Name = "foo";
        }
    }
}

下面的代码(ExampleClass.cs):

using System.ComponentModel;

namespace SimpleBinding
{
    public class ExampleClass : INotifyPropertyChanged
    {
        private string _name;

        public string Name
        {
            get
            {
                return _name;
            }

            set
            {
                if (_name == value) return;

                _name = value;
                OnPropertyChanged("Name");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

第一种方法应该如何工作?

标签: wpf

解决方案


只需触发属性的 PropertyChanged 事件T

private ExampleClass t;
public ExampleClass T
{
    get { return t; }
    private set
    {
        if (t != value)
        {
            t = value;
            OnPropertyChanged(nameof(T));
        }
    }
}

当您为T属性分配新值并希望{Binding T.Name}更新其目标时,需要更改通知:

private void Button_Click(object sender, RoutedEventArgs e)
{
    ...
    T = new ExampleClass(); // requires change notification
    label2.DataContext = T; // avoid this
    T.Name = "foo";
}

您应该更喜欢使用{Binding T.Name}over{Binding Name}以避免需要设置除 MainWindow 之外的任何其他 DataContext。


推荐阅读