wpf 每次调用方法时创建一个对象的新实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16995365/
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
Creating a new instance of an object each time method is called
提问by Jason D
Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>();
adventurerWindowVM.Adv = message.Argument;
var adventurerWindow = new AdventurerView()
{
DataContext = adventurerWindowVM
};
adventurerWindow.Show();
});
This code is fairly simple; it just opens a new window and sets the DataContext of the new window. The problem I'm having is that if I execute this twice, the content of the first instance will be overwritten and be set to that of the second since adventurerWindowVMis the DataContext of both windows and it is overwritten each time this code is called. I'm looking for a way to prevent this; I'd like to be able to open multiple windows using this message and have each of them be unique, but thus far I haven't figured out a way to do so. Any advice would be greatly appreciated. I apologize for the vague title; I was unsure of what to name this question. (Also, I know that this isn't a method. What would this block of code be called?)
这段代码相当简单;它只是打开一个新窗口并设置新窗口的 DataContext。我遇到的问题是,如果我执行两次,第一个实例的内容将被覆盖并设置为第二个实例的内容,因为adventurerWindowVM这是两个窗口的 DataContext 并且每次调用此代码时都会被覆盖。我正在寻找一种方法来防止这种情况;我希望能够使用此消息打开多个窗口并让每个窗口都是唯一的,但到目前为止我还没有找到这样做的方法。任何建议将不胜感激。我为模糊的标题道歉;我不确定如何命名这个问题。(另外,我知道这不是一个方法。这段代码会被称为什么?)
Update:I'm using MVVM Light and my code is based off of an example somebody provided for me in this answer: https://stackoverflow.com/a/16994523/1667020
更新:我正在使用 MVVM Light,我的代码基于某人在此答案中为我提供的示例:https: //stackoverflow.com/a/16994523/1667020
Here is some code from my ViewModelLocator.cs
这是我的 ViewModelLocator.cs 中的一些代码
public ViewModelLocator()
{
_main = new MainViewModel();
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<GameViewModel>();
SimpleIoc.Default.Register<AdventurerViewModel>();
}
回答by Viv
Having given the other answer, I guess I can say the IoC container used here is just SimpleIoCfrom MvvmLight and to get a new instance of the VM on every GetInstance(...)all you need to do is pass in a unique key every time when trying to resolve an instance of the VM.
给出另一个答案后,我想我可以说这里使用的 IoC 容器仅SimpleIoC来自 MvvmLight 并且要在每次GetInstance(...)尝试解析实例时都传递一个唯一的键,您需要做的就是获取 VM 的新实例虚拟机的。
So you can switch
所以你可以切换
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>();
to
到
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>(System.Guid.NewGuid().ToString());
However as mentioned by the author of MVVMLight Herethese VM's will get cached and we need to get rid of them when no longer needed. In your case probably when the Windowis closed.
然而,随着由MVVMLight笔者提到这里,这些虚拟机将得到缓存,我们需要摆脱他们的时候不再需要。在您的情况下,可能是在Window关闭时。
Thus I'd have that entire lambda something like:
因此,我有整个 lambda 类似的东西:
Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
var uniqueKey = System.Guid.NewGuid().ToString();
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>(uniqueKey);
adventurerWindowVM.Adv = message.Argument;
var adventurerWindow = new AdventurerView()
{
DataContext = adventurerWindowVM
};
adventurerWindow.Closed += (sender, args) => SimpleIoc.Default.Unregister(uniqueKey);
adventurerWindow.Show();
});
Note:
笔记:
While this is somewhat longer 3 lines compared to just creating a new VM yourself with (new AdventurerViewModel()) I still favor this because if you use an IoC container to manage LifeTime of your VM's, then have it manage them completely. Don't really like mix-n-match when not needed. Rather keep the IoC Container doing what it's meant to do.
虽然与使用 ( new AdventurerViewModel())自己创建新 VM 相比,这 3 行要长一些,但我仍然喜欢这一点,因为如果您使用 IoC 容器来管理 VM 的 LifeTime,则让它完全管理它们。在不需要时不要真的喜欢混合匹配。而是让 IoC 容器做它应该做的事情。
If you need more control over VM injection and Life-time management look at more sophisticated Ioc controllers such as Unity. SimpleIoCwas just meant to be a simple get your feet "wet" in IoC kind of container and it does a very good job in that regard.
如果您需要更多地控制 VM 注入和生命周期管理,请查看更复杂的 Ioc 控制器,例如Unity。SimpleIoC只是为了让你的脚在 IoC 类型的容器中“弄湿”,它在这方面做得非常好。
回答by Kosala W
I think you are trying to use the same instanceof your ViewModelwith multiple views. So the views will obviously overwrite each others viewmodel contents.
我认为你要使用相同的实例您的视图模型与多个视图。所以视图显然会覆盖彼此的视图模型内容。
What if you do this;
如果你这样做怎么办?
Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
var adventurerWindowVM = new AdventurerViewModel();
adventurerWindowVM.Adv = message.Argument;
var adventurerWindow = new AdventurerView()
{
DataContext = adventurerWindowVM
};
adventurerWindow.Show();
});
回答by Tim Long
It's a method call, passing in an anonymous method using a lambda expression.
这是一个方法调用,使用 lambda 表达式传入一个匿名方法。
It looks like you are getting your AdventurerViewModelfrom some sort of IoC container. How is the IoC container configured? In particular, what is the scope of the objects it gives you back? If you have the IoC configured to create objects in singleton scope, for example, then you will always get back a reference to the same object each time. You may need to configure the scope of the object in your IoC container so that it gives you back a fresh copy every time.
看起来您是AdventurerViewModel从某种 IoC 容器中获取的。IoC 容器是如何配置的?特别是,它返回给你的对象的范围是什么?例如,如果您将 IoC 配置为在单例范围内创建对象,那么您每次都会返回对同一对象的引用。您可能需要在 IoC 容器中配置对象的范围,以便它每次都为您提供一个新的副本。
How you do that will depend on your IoC container. Without knowing which IoC framework you are using or seeing its configuration, it's impossible to make any further comment.
您如何做到这一点取决于您的 IoC 容器。在不知道您使用的是哪个 IoC 框架或查看其配置的情况下,无法做出任何进一步的评论。

