用于引发依赖属性RaisePropertyChanged事件的MVVM模式

本文关键字:事件 MVVM 模式 RaisePropertyChanged 属性 依赖 用于 | 更新日期: 2023-09-27 18:08:57

我有一些只读属性,它们根据视图模型中的兄弟属性返回一个值。为了将它们绑定到XAML,我需要向兄弟属性添加额外的RaisePropertyChanged事件。这感觉有点不优雅。

一个简化的例子:

public bool IsPurchased
{
    get
    {
        return _IsPurchased;
    }
    set
    {
        if (_IsPurchased == value) return;
        _IsPurchased = value;
        RaisePropertyChanged("IsPurchased");
        RaisePropertyChanged("IsAvailableToUse");
    }
}
private bool _IsPurchased = false;
public bool IsDownloaded
{
    get
    {
        return _IsDownloaded;
    }
    set
    {
        if (_IsDownloaded == value) return;
        _IsDownloaded = value;
        RaisePropertyChanged("IsDownloaded");
        RaisePropertyChanged("IsAvailableToUse");
    }
}
private bool _IsDownloaded = false;
public bool IsAvailableToUse
{
    get
    {
        return IsPurchased && IsDownloaded;
    }
}

有没有人有一个好的模式,可以在贡献属性本身中删除额外的RaisePropertyChanged("IsAvailableToUse"),并使这种场景更容易管理?可以在视图模型的集中位置添加这些类型的映射。

用于引发依赖属性RaisePropertyChanged事件的MVVM模式

看看这个https://github.com/steinborge/ProxyTypeHelper。它会做你的MVVM/WPF,并自动连接propertychangeevents。所以你的例子是这样的:

    public bool IsDownloaded {get;set;}
    public bool IsPurchased { get; set; }
    [LinkToProperty("IsDownloaded")]
    [LinkToProperty("IsPurchased")]
    public bool IsAvailableToUse
    {
        get
        {
            return IsPurchased && IsDownloaded;
        }
    }
    [LinkToCommand("PurchaseCommand")]
    private void btnPurchase()
    {
    }
    [LinkToCommand("DownloadCommand")]
    private void btnDownload()
    {
    }

据我所知,这种模式在MVVM中相当常见。如果你想把所有的属性分组在一起,你可以覆盖你的RaisePropertyChanged的实现,以下面的方式处理分组的情况。

   protected override void RaisePropertyChanged(string propertyName = null)
    {
        PropertyChangedEventHandler handler = this.PropertyChangedHandler;
        switch (propertyName)
        {
            case "IsDownloaded":
            case "IsAvailableToUse":
            case "IsPurchased":
                if (handler != null) handler(this, new PropertyChangedEventArgs("IsDownloaded"));
                if (handler != null) handler(this, new PropertyChangedEventArgs("IsAvailableToUse"));
                if (handler != null) handler(this, new PropertyChangedEventArgs("IsPurchased"));
                break;
            default:
                if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
                break;
        }
    }

在一个不相关的注意事项上,我注意到你的一个属性被命名为"IsAvailableToUse",似乎该属性可能是命令绑定的开关。如果你基于这个布尔值启用/禁用按钮,那么我建议声明一个iccommand和CanExecute。它可以更优雅,因为按钮有这个框架内置的有用和优雅的功能。