当初始化新的ViewModel时,传递数据的最佳方法是什么?

7
我正在使用MVVM-Light框架开发一个WPF数据库应用程序。我使用SimpleIOC来注入我的数据服务,我的ViewModel与XAML文件中的视图相连接。然而,当打开新的ViewModel时,我通常还需要传递另一个对象给ViewModel(假设我传递的是CarId的整数,这样我就可以从数据库中获取实际的汽车)。
目前,我在InitializeComponent()之后使用View上的信使来传递此内容,然后由ViewModel接收。当前这种方法可以工作,但也有一些缺点。
首先,直到调用ViewModel的构造函数之后才会发送消息。假设我在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);
        }
    }

当构造函数被调用时,我必须在视图模型构造函数中初始化ThisCar,否则在创建ViewModel时,ThisCar.Brand会得到null错误。

ThisCar = new CarObject();

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

ThisCar = webService.GetCar(carId);

然而,当我这样做时,品牌属性并没有被更新,因为没有任何调用Brand的OnPropertyChanged方法。
我有两个解决方案,但它们感觉更像是hack。 第一个是手动调用需要更新的所有属性的OnPropertyChanged方法。第二个是我删除了所有小属性,并直接将所有内容绑定到ThisCar属性上(这意味着我必须在模型中实现INotifyPropertyChanged)。
请告诉我是否只是我的一些挑剔,或者是否有更好的方法来解决这个问题。我的做法虽然可行,但让我感觉不对劲。谢谢!
2个回答

2

好的,这是我想出来的,如果这个想法很糟糕,请告诉我。

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

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

为了在新的视图模型中接收,我将以下内容放入视图模型的构造函数中:

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

在不破坏MVVM模式的情况下,这似乎可以解决问题。由于我使用的IOC容器将所有接口成员创建为静态成员,因此我将在其余的视图中拥有这些数据。

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


当您拥有目录应用程序并且视图被回收时,这将无法工作。由于您仅记住上次显示的最后一项,因此会丢失活动项目堆栈。 - Toni Petrina

1

我支持在模型中实现INotifyPropertyChanged,使其能够通知其变化。原因如下:

  1. 可能会有多个地方/视图需要使用相同的模型,您不希望在每个ViewModel中都要关注哪个属性更改应该引发其他哪些属性更改。坦白地说,这很混乱且容易出错。

  2. 有时,在VM层中我们可能需要监听模型的变化,因此自我通知的模型也有所帮助。

谢谢


现在这很有意义,我只是记得当我第一次学习MVVM时,看到的信息是将INotifyPropertyChange保持在模型之外。您有没有关于如何在不使用messenger的情况下向viewmodel传递参数的建议? - Daryl Behrens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接