具有与通用模型相同的属性的ViewModel

时间:2019-03-27 13:55:53

标签: c# mvvm data-binding inotifypropertychanged .net-4.6

我正在尝试在以下代码中为用例创建代码,其中通用ViewModel类从其模型“捕获”所有属性,并提供具有相同名称和类型的属性,并触发{{ 1}}事件以进行数据绑定。

有办法吗?我正在使用.NET 4.6。

PropertyChanged

2 个答案:

答案 0 :(得分:2)

您可以使用Fody自动插入在 compile 时引发模型类所有属性的PropertyChanged事件的代码。

然后,您可以直接绑定到Rectangle,而无需修改它并显式实现INotifyPropertyChanged接口。

否则,恐怕您将不得不在每个视图模型中一个一个地定义每个属性,或者在构建之前想出一种自动生成视图模型类的方法。

答案 1 :(得分:0)

您正在寻找类似的东西吗?

using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;

public class Rectangle : INotifyPropertyChanged
{
    private double height;

    public double Width { get; set; }
    public double Height { get => height; set => SetField(ref height, value); }

    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

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

public class RectangleViewModel : MagicViewModel<Rectangle>
{
    public RectangleViewModel(Rectangle model)
        : base(model)
    {
        this.model = model;
        model.PropertyChanged += (s, e) => OnPropertyChanged(e.PropertyName);
    }

    private Rectangle model;

    public Rectangle Model { get => model; set => SetField(ref model, value); }
}

public class MagicViewModel<TModel> : INotifyPropertyChanged
{
    protected readonly TModel _model;

    public MagicViewModel(TModel model)
    {
        _model = model;
    }

    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public 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;
    }
    #endregion
}

public class Program
{
    public static void Main(string[] args)
    {
        var vm = new RectangleViewModel(new Rectangle());
        var calls = 0;
        vm.PropertyChanged += (sender, propChangedArgs) => calls++;
        vm.Model.Height = 10;  // magic happened here
        Debug.Assert(calls > 0);
    }
}