简体   繁体   English

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

[英]Best Way to Pass Data to new ViewModel when it is initiated

I am working on an WPF database application using the MVVM-Light Framework. 我正在使用MVVM-Light Framework处理WPF数据库应用程序。 I am using SimpleIOC to inject my Data Services, and my ViewModels are connected to the view from the XAML file. 我使用SimpleIOC来注入我的数据服务,我的ViewModel连接到XAML文件中的视图。 However, when opening new View Models I usually also need to pass another object to the View Model (lets say I am passing a integer of a CarId so I can grab the actual Car from a database). 但是,在打开新的视图模型时,我通常还需要将另一个对象传递给视图模型(假设我传递的是CarId的整数,因此我可以从数据库中获取实际的Car)。

Right now I am passing this by using a messenger on the View, after InitializeComponent(). 现在我在InitializeComponent()之后使用View上的messenger传递这个。 This is then caught by the View Model. 然后由View Model捕获。 This currently does work, however it has some set backs. 这目前确实有效,但它有一些挫折。

First, the Message does not get sent until after the Constructor of the View Model is called. 首先,在调用视图模型的构造函数之前,不会发送消息。 Lets say I had a ThisCar object Property in the ViewModel, and I had secondary properties like a string called Brand, that returns ThisCar.Brand. 假设我在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);
        }
    }

Now when the constructor gets called, I have to initialize ThisCar in the View Model Constructor Like so, otherwise I get a null error on ThisCar.Brand when the ViewModel gets created. 现在当构造函数被调用时,我必须在View Model Constructor中初始化ThisCar,就像这样,否则我在创建ViewModel时会在ThisCar.Brand上得到null错误。

ThisCar = new CarObject();

Then, after it is initialized to an empty object, the Message will get called, and I will pull the real Car from the Database based on the Car ID. 然后,在将其初始化为空对象后,将调用Message,我将根据Car ID从数据库中提取真实Car。

ThisCar = webService.GetCar(carId);

However, when I do this, the Brand Property does not get updated, because nothing is calling the OnPropertyChanged for the Brand. 但是,当我这样做时,品牌属性不会更新,因为没有任何东西为品牌调用OnPropertyChanged。

I have two work arounds, but they feel more like hacks to me. 我有两个工作,但他们觉得更像是我的黑客。 First on is manually calling the OnPropertyChanged for any properties that need to be updated. 首先,为任何需要更新的属性手动调用OnPropertyChanged。 Second is I remove all the small properties, and bind everything directly to the ThisCar property (which means I have to implement INotifyPropertyChanged in my model). 其次是删除所有小属性,并将所有内容直接绑定到ThisCar属性(这意味着我必须在我的模型中实现INotifyPropertyChanged)。

Please let me know if I am just being picky, or if there is a better way to do this. 如果我只是挑剔,或者有更好的方法,请告诉我。 The way I am doing it works, but just doesn't sit right with me. 我这样做的方式有效,但不能和我坐在一起。 Thank you. 谢谢。

Ok, so here is what I came up with, please let me know if this is a horrible idea. 好的,所以这就是我想出的,如果这是一个可怕的想法,请告诉我。

I created an Interface called IRepository since I am using Dependency Injections to create View Models. 我创建了一个名为IRepository的接口,因为我使用依赖注入来创建View模型。 Here is the implementation: 这是实施:

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

Next I create a class which inherits from IRepository 接下来,我创建一个继承自IRepository的类

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

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

Now to pass the value into the repository, I put this into the parent View Model 现在将值传递到存储库中,我将其放入父视图模型中

 r.SetCarId(13);

And to recieve in the new view Model I put this in the View Models Constructor: 并且在新视图中接收模型我把它放在View Models Constructor中:

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

This seems to me to fix the problem, without breaking the MVVM pattern, and since the IOC Container I am using creates all the Interface Members as staic, I will have this data throughout the rest of my Views. 在我看来,这可以解决问题,而不会破坏MVVM模式,并且由于我使用的IOC容器创建了所有接口成员,因此我将在其余视图中包含此数据。

The main problem I have with this is that it feels like a global variable, but this is the best I could come up with on it. 我遇到的主要问题是它感觉像是一个全局变量,但这是我能想到的最好的变量。 Please let me know if this is a really bad idea. 如果这是一个非常糟糕的主意,请告诉我。 Thank you. 谢谢。

I will vote for making models able to notify there changes ie implementing INotifyPropertyChanged in models. 我会投票让模型能够通知那些变化,即在模型中实现INotifyPropertyChanged。 Two reasons: 两个原因:

  1. There may be multiple places/views you might need to use the same model and you would not like to take care in each ViewModel as which property change should raise which other property changes. 您可能需要使用相同模型的多个位置/视图,并且您不希望在每个ViewModel中注意哪个属性更改应该引发哪个其他属性更改。 Frankly thats messy and buggy. 坦率地说那是凌乱和马车。

  2. Sometimes, in the VM layer we might need to listen to changes in models, so in that case also self notifying model helps. 有时,在VM层中,我们可能需要监听模型中的更改,因此在这种情况下,自我通知模型也会有所帮助。

Thanks 谢谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将事件传递给ViewModel的最佳方法是什么? - What's the best way to pass event to ViewModel? MVVM-Light将数据传递到新的ViewModel - MVVM-Light pass data to new ViewModel 在MVVMCross中将对象传递给“导航到”viewmodel的最佳方法是什么? - What is the best way to pass objects to “navigated to” viewmodel in MVVMCross? 在视图之间传递数据的最佳方法是什么? - What is the best way to pass data between views? 在类和表单之间传递数据的最佳方法? - Best way to pass data in between classes and forms? null 时创建新 SqlConnection 的最佳方法 - Best way to create new SqlConnection when is null 寻找在“添加新”视图上提供ViewModel的最佳方法,仅此视图的一部分/作为提交POST响应的另一种方法 - Looking for the best way to provide a ViewModel on “Add new” View and just part of it / different one as its submit POST response 使回调值返回启动异步方法的函数的最佳方法? - Best way to get callback value back to the function that initiated async method? 将模型传递给MVC6中的新ViewDataDictionary的最佳方法 - Best way to pass a model to a new ViewDataDictionary in MVC6 创建新商机实体时传递查找 GUID 的最佳方式 - Best way to pass a Lookup GUID while creating a new Opportunity entity
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM