wpf 启动时将数据传递给新 ViewModel 的最佳方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18497991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best Way to Pass Data to new ViewModel when it is initiated
提问by Daryl Behrens
I am working on an WPF database application using the MVVM-Light Framework. I am using SimpleIOC to inject my Data Services, and my ViewModels are connected to the view from the XAML file. 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).
我正在使用 MVVM-Light 框架开发 WPF 数据库应用程序。我使用 SimpleIOC 来注入我的数据服务,并且我的 ViewModel 从 XAML 文件连接到视图。但是,当打开新的视图模型时,我通常还需要将另一个对象传递给视图模型(假设我传递的是 CarId 的整数,以便我可以从数据库中获取实际的汽车)。
Right now I am passing this by using a messenger on the View, after InitializeComponent(). This is then caught by the View Model. This currently does work, however it has some set backs.
现在我在 InitializeComponent() 之后通过在视图上使用信使来传递它。然后被视图模型捕获。这目前确实有效,但是它有一些挫折。
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.
现在,当构造函数被调用时,我必须像这样在视图模型构造函数中初始化 ThisCar,否则在创建 ViewModel 时我会在 ThisCar.Brand 上收到空错误。
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 将被调用,我将根据汽车 ID 从数据库中提取真正的汽车。
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. 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).
我有两个变通方法,但它们对我来说更像是黑客。首先是为需要更新的任何属性手动调用 OnPropertyChanged。其次是我删除了所有小属性,并将所有内容直接绑定到 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.
如果我只是挑剔,或者是否有更好的方法来做到这一点,请告诉我。我这样做的方式有效,但只是不适合我。谢谢你。
采纳答案by Daryl Behrens
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. Here is the implementation:
我创建了一个名为 IRepository 的接口,因为我使用依赖注入来创建视图模型。这是实现:
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:
为了在新的视图模型中接收我把它放在视图模型构造函数中:
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.
我遇到的主要问题是它感觉像是一个全局变量,但这是我能想到的最好的方法。请让我知道这是否是一个非常糟糕的主意。谢谢你。
回答by Nitin
I will vote for making models able to notify there changes i.e implementing INotifyPropertyChanged in models. Two reasons:
我将投票支持使模型能够通知更改,即在模型中实现 INotifyPropertyChanged。两个原因:
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. Frankly thats messy and buggy.
Sometimes, in the VM layer we might need to listen to changes in models, so in that case also self notifying model helps.
可能有多个地方/视图您可能需要使用相同的模型,并且您不希望在每个 ViewModel 中注意哪些属性更改应该引发哪些其他属性更改。坦率地说,那是凌乱和马车。
有时,在 VM 层,我们可能需要监听模型的变化,所以在这种情况下,自我通知模型也有帮助。
Thanks
谢谢

