wpf 泛型可绑定属性无法正常工作

5uzkadbs  于 2023-10-22  发布在  其他
关注(0)|答案(2)|浏览(163)

(开始前:我正在使用.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的属性的一点是,它们添加了太多的代码,在我看来,这有点膨胀了源代码。今天,我试图创建一种方法,不必在任何地方编写(用snippet生成)整个属性。

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;
    }
}

这看起来像是一个非常干净的解决方案,可以避免到处都有相同的样板代码。很遗憾,好像不管用。
有谁能告诉我这不起作用的原因吗?或者,如果有一个调整,这可能工作?

vwhgwdsa

vwhgwdsa1#

你的“Generic bindable property”实际上不是一个 property,而是一个 field。要将其变为属性,add getters

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

你可以在这篇文章中找到现成的解决方案:Implementing INotifyPropertyChanged - does a better way exist?

tkclm6bt

tkclm6bt2#

我不喜欢那些必须调用OnPropertyChanged的属性的一点是,它们添加了太多的代码,在我看来,这有点膨胀了源代码。
您可能需要考虑使用源代码生成器,例如Fody。在编译时,它注入引发PropertyChanged事件的代码。
有谁能告诉我这不起作用的原因吗?
ReadFlagWriteFlag必须是public properties 才能绑定到它们:

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

相关问题