通用可绑定属性无法正常工作

问题描述 投票:0回答:2

(开始之前:我正在使用 .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;
    }
}

这看起来是一个非常干净的解决方案,可以避免到处都有相同的样板代码。可悲的是,它似乎不起作用。

谁能告诉我这不起作用的原因吗?或者,如果稍微调整一下,这可以工作吗?

wpf data-binding inotifypropertychanged
2个回答
0
投票

对于必须调用 OnPropertyChanged 的属性,我不喜欢的一件事是它们添加了太多代码,在我看来,源代码有点膨胀。

您可能需要考虑使用源生成器,例如Fody。在编译时,它会注入

PropertyChanged
事件的代码。

谁能告诉我这不起作用的原因吗?

ReadFlag
WriteFlag
必须是公共 属性 才能绑定到它们。


0
投票

您的“通用可绑定属性”并不是真正的属性,它是一个字段。要从中创建属性,请添加 getter:

public class Permissions
{
    BindableProperty<bool> ReadFlag { get; } = new BindableProperty<bool>();
    BindableProperty<bool> WriteFlag { get; } = new BindableProperty<bool>();
}

您可能会在这篇文章中找到现成的解决方案:实现 INotifyPropertyChanged - 是否存在更好的方法?

© www.soinside.com 2019 - 2024. All rights reserved.