启动时将数据传递给新ViewModel的最佳方法

时间:2013-08-28 20:54:27

标签: c# wpf mvvm mvvm-light

我正在使用MVVM-Light Framework处理WPF数据库应用程序。我使用SimpleIOC来注入我的数据服务,我的ViewModel连接到XAML文件中的视图。但是,在打开新的视图模型时,我通常还需要将另一个对象传递给视图模型(假设我传递的是CarId的整数,因此我可以从数据库中获取实际的Car)。

现在我在InitializeComponent()之后使用View上的messenger传递此信息。然后由View Model捕获。这目前确实有效,但它有一些挫折。

首先,在调用视图模型的构造函数之前,不会发送消息。假设我在ViewModel中有一个ThisCar对象属性,并且我有一个二级属性,如一个名为Brand的字符串,它返回ThisCar.Brand。

    public const string ThisPersonPropertyName = "ThisCar";
    private Model.Car _thisCar;
    public Model.Car ThisCar
    {
        get
        {
            return _thisCar;
        }

        set
        {
            if (_thisCar== value)
            {
                return;
            }

            RaisePropertyChanging(ThisCarPropertyName);
            _thisCar= value;
            RaisePropertyChanged(ThisCarPropertyName);
        }
    }

    public const string BrandPropertyName = "Brand";
    public string Brand
    {
        get
        {
            return ThisCar.Brand;
        }

        set
        {
            if (ThisCar.Brand == value)
            {
                return;
            }

            RaisePropertyChanging(BrandPropertyName);
            ThisCar.Brand = value;
            RaisePropertyChanged(BrandPropertyName);
        }
    }

现在当构造函数被调用时,我必须在View Model Constructor中初始化ThisCar,就像这样,否则当ViewModel被创建时,我会在ThisCar.Brand上得到一个null错误。

ThisCar = new CarObject();

然后,在初始化为空对象之后,将调用Message,我将根据Car ID从数据库中提取真实的Car。

ThisCar = webService.GetCar(carId);

但是,当我这样做时,品牌属性不会更新,因为没有任何东西为品牌调用OnPropertyChanged。

我有两个工作,但他们觉得更像是我的黑客。首先,为任何需要更新的属性手动调用OnPropertyChanged。其次是删除所有小属性,并将所有内容直接绑定到ThisCar属性(这意味着我必须在我的模型中实现INotifyPropertyChanged)。

如果我只是挑剔,或者有更好的方法,请告诉我。我这样做的方式有效,但不能和我坐在一起。谢谢。

2 个答案:

答案 0 :(得分:2)

好的,所以这就是我想出来的,如果这是一个可怕的想法,请告诉我。

我创建了一个名为IRepository的接口,因为我使用依赖注入来创建View模型。以下是实施:

public interface IRepository
{
    void GetCarId(Action<int> callback);
    void SetCarId(int value);
}

接下来,我创建一个继承自IRepository

的类
public class Repository : IRepository
{
    private int CarId;
    public void GetCarId(Action<int> callback)
    {
        callback(CarId);
    }

    public void setDictionary(int carId)
    {
        CarId = carId;
    }
}

现在将值传递到存储库,我将其放入父视图模型

 r.SetCarId(13);

并且在新视图中接收模型我把它放在View Models Constructor中:

    public View2ViewModel(IChildView i, IRepository r)
    {
        int CarId;
        r.GetCarId((id) => CarId = id);
        thisCar = GetCarFromDatabase(CarId);
    }

在我看来,在不破坏MVVM模式的情况下解决了这个问题,而且由于我使用的IOC容器创建了所有的接口成员,所以我将在其余的视图中获得这些数据。

我遇到的主要问题是它感觉像是一个全局变量,但这是我能想到的最好的变量。如果这是一个非常糟糕的主意,请告诉我。谢谢。

答案 1 :(得分:1)

我会投票让模型能够通知那些变化,即在模型中实现INotifyPropertyChanged。有两个原因:

  1. 您可能需要使用相同模型的多个位置/视图,并且您不希望在每个ViewModel中注意哪个属性更改应该引发哪个其他属性更改。坦率地说那很麻烦和马车。

  2. 有时,在VM层中我们可能需要监听模型中的更改,因此在这种情况下,自我通知模型也会有所帮助。

  3. 由于