(开始之前:我正在使用 .NET Framework 4.8)
我一直在 WPF 中闲逛,我厌倦了不断键入用于绑定的属性。我现在使用代码片段来输入样板代码。
过了一段时间,我厌倦了总是在每个“模型”中粘贴通知属性更改代码,我创建了一个
BindableBase
,这是我学到的一种常见做法。类看起来像这样:
public class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
/// <summary>
/// Sets the value of a field of type T. <br/>
/// If new field value differs from old value, the funtion returns true. <br/>
/// If the value remains unchanged, the function returns false.
/// </summary>
/// <typeparam name="T">The type of the property / field.</typeparam>
/// <param name="field">A reference to the field that should be updated.</param>
/// <param name="value">The new value to be assigned to the property / field.</param>
/// <param name="propertyName">The variable name in code. Leave empty to let the compiler do this for you.</param>
/// <returns>True on field value change, false if field value remains the same.</returns>
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
public delegate void PropertyValueChangedEventHandler<T>(T newValue);
}
我的属性是这样的
private object privateProp;
public object PublicProp
{
get => privateProp;
set => SetField(ref privateProp, value);
}
对于必须调用 OnPropertyChanged 的属性,我不喜欢的一件事是它们添加了太多代码,在我看来,源代码有点膨胀。今天,我尝试创建一种方法,不必在任何地方编写(使用片段生成)整个属性。
public class BindableProperty<T> : BindableBase
{
private T value;
public T Value
{
get => value;
set => SetField(ref value, value);
}
}
我想使用如下:
<StackPanel Name="PermissionsPanel">
<CheckBox Name="ReadCheckBox" IsChecked="{Binding ReadFlag.Value}" />
<CheckBox Name="WriteCheckBox" IsChecked="{Binding WriteFlag.Value}" />
<StackPanel />
public class Permissions
{
BindableProperty<bool> ReadFlag = new BindableProperty<bool>();
BindableProperty<bool> WriteFlag = new BindableProperty<bool>();
}
// ...
public class SomeWindow : Window
{
privatye readonly Permissions permissions = new Permissions();
public SomeWindow()
{
InitializeComponent();
PermissionsPanel.DataContext = permissions;
}
}
这看起来是一个非常干净的解决方案,可以避免到处都有相同的样板代码。可悲的是,它似乎不起作用。
谁能告诉我这不起作用的原因吗?或者,如果稍微调整一下,这可以工作吗?
对于必须调用 OnPropertyChanged 的属性,我不喜欢的一件事是它们添加了太多代码,在我看来,源代码有点膨胀。
您可能需要考虑使用源生成器,例如Fody。在编译时,它会注入
PropertyChanged
事件的代码。
谁能告诉我这不起作用的原因吗?
ReadFlag
和 WriteFlag
必须是公共 属性 才能绑定到它们。
您的“通用可绑定属性”并不是真正的属性,它是一个字段。要从中创建属性,请添加 getter:
public class Permissions
{
BindableProperty<bool> ReadFlag { get; } = new BindableProperty<bool>();
BindableProperty<bool> WriteFlag { get; } = new BindableProperty<bool>();
}
您可能会在这篇文章中找到现成的解决方案:实现 INotifyPropertyChanged - 是否存在更好的方法?