首页 > 解决方案 > 使用组合的类中的 MvvmLight

问题描述

我有一个 ViewModel,派生自MvvmLight.ViewModelBase它使用组合来重用其他类:

我想在组合中重用的类的简化版本:

class TimeFrameFactory
{
    public DateTime SelectedTime {get; set;}

    public ITimeFrame CreateTimeFrame() {...}
}

class GraphFactory
{
     public int GraphWidth {get; set;}

     public IGraph CreateGraph(ITimeframe timeframe) {...}
}

我的 ViewModel,派生自 MvvmLight ViewModelBase 是这两个的组合:

class MyViewModel : ViewModelBase
{
    private readonly TimeFrameFactory timeFrameFactory = new TimeFrameFactory();
    private readonly GraphFactory graphFactory = new GraphFactory();

    private Graph graph;

    // standard MVVM light method to get/set a field:
    public Graph Graph
    {
        get => this.Graph;
        private set => base.Set(nameof(Graph), ref graph, value);
    }

    // this one doesn't compile:
    public DateTime SelectedTime 
    {
        get => this.timeFrameFactory.SelectedTime;
        set => base.Set(nameof(SelectedTime), ref timeFrameFactory.SelectedTime, value);
    }

    // this one doesn't compile:
    public int GraphWidth
    {
        get => this.timeFrameFactory.GraphWidth;
        set => base.Set(nameof(GraphWidth), ref timeFrameFactory.GraphWidth, value);
    }

    public void CreateGraph()
    {
        ITimeFrame timeFrame = this.timeFrameFactory.CreateTimeFrame();
        this.Graph = this.GraphFactory.CreateGraph(timeFrame);
    }
}

使用字段获取/设置有效,但如果我想将属性设置转发给复合对象,我不能使用base.Set

set => base.Set(nameof(GraphWidth), ref timeFrameFactory.GraphWidth, value);

属性上不允许使用 ref。

我当然可以写:

    public int GraphWidth
    {
        get => this.timeFrameFactory.GraphWidth;
        set
        {
            base.RaisePropertyChanging(nameof(GraphWidh));
            base.Set(nameof(GraphWidth), ref timeFrameFactory.GraphWidth, value);
            base.RaisePropertyChanged(nameof(GraphWidh));
        }
    }

如果您必须为很多属性执行此操作,那就太麻烦了。有没有一种巧妙的方法可以做到这一点,可能类似于ObservableObject.Set

标签: c#mvvmmvvm-lightobservablecollection

解决方案


好吧,基本方法需要能够读取(用于比较)和写入传递的字段/属性,因此 ref.

由于您不能通过引用传递属性,我认为您被迫编写另一个基本方法

A) 接受 getter/setter 代表。(冗长/烦人)

public int GraphWidth
{
    get => this.timeFrameFactory.GraphWidth;
    set => base.Set(nameof(GraphWidth), () => timeFrameFactory.GraphWidth, x => timeFrameFactory.GraphWith = x, value);
}

或者

B)传递一个Expression<Func<T>>包含属性并使用反射来提取属性并在基础中获取/设置它(慢,但也可能提取名称)

public int GraphWidth
{
    get => this.timeFrameFactory.GraphWidth;
    set => base.Set(() => timeFrameFactory.GraphWidth, value);
}

推荐阅读