wpf - 使用 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));
}
}
}
第一种方法应该如何工作?
解决方案
只需触发属性的 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。
推荐阅读
- git - 如何以另一个用户身份提交和推送
- swift - AudioKit,将 AVAudioPCMBuffer 数组导出到带有淡入/淡出的音频文件
- javascript - JavaScript 让 Python 的 Selenium 陷入困境
- python-3.x - 如何在 QGIS 中查询属性表以返回子集的总和
- php - PHP curl -- 如果已经登录到某个网站,如何获取其他页面的内容
- android - 程序类型已经存在:com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable
- python - 如何将两个程序合并为一个程序?
- python - Kivy.garden.progressspinner 中的黑线
- debugging - WatchOS5 - 如何调试苹果手表应用程序?
- prolog - 防止回溯而不切割