C# MvvmLight:如何取消订阅;RaisePropertychanged";事件
我在使用MvvmLight的WPF应用程序中遇到问题 我的申请:C# MvvmLight:如何取消订阅;RaisePropertychanged";事件,c#,.net,wpf,mvvm-light,C#,.net,Wpf,Mvvm Light,我在使用MvvmLight的WPF应用程序中遇到问题 我的申请: 我有一个带有菜单的主视图,每个菜单项都将打开一个新视图(每个菜单项都不同) 每个MenuItem都绑定到我的MainViewModel的RelayCommand 在my MainView模型中,RelayCommand只需将Messenger.Default.Send(这是“ShowMyView”)发送到MainView 在我的MainView中,我在消息“ShowMyView”上注册,操作如下: var v=new MyVi
- 我有一个带有菜单的主视图,每个菜单项都将打开一个新视图(每个菜单项都不同)
- 每个MenuItem都绑定到我的MainViewModel的RelayCommand
- 在my MainView模型中,RelayCommand只需将Messenger.Default.Send(这是“ShowMyView”)发送到MainView
- 在我的MainView中,我在消息“ShowMyView”上注册,操作如下:
var v=new MyView();
v、 所有者=此;
v、 ShowDialog();
Messenger.Default.Unregister(v)代码>
此新视图(MyView)绑定在包含属性的viewmodel(MyViewModel)上。
此视图的元素(文本框、radiobutton等)绑定到这些属性
当我关闭“MyView”时,它被释放,我返回到我的主视图,但“MyViewModel”仍然存在
问题:
当我第一次打开“MyView”时,绑定工作正常,如果“MyViewModel”设置了一个属性,则调用RaisePropertyChanged,然后调用一次该属性的“get”
但是如果我打开和关闭我的视图20次,在第20次,当一个RaisePropertyChanged被调用时,这个属性的get被调用20次
问题:
那么,当我关闭视图时,如何取消订阅这些“RaisePropertyChanged”
我很清楚,很抱歉我的英语不好
编辑:使用代码
编辑BIS
请在我的github上找到发生问题的完整项目,而不是放置部分代码
运行应用程序时,主窗口将启动:
您可以在调试输出中看到:
Starting
Creating NewViewModel
然后,当我单击NewView菜单时,NewView将打开:
您可以在调试输出中看到:
Initialize NewViewModel and set MyBool to true
MyBool Set call + RaiseProperty
MyBool Get call
MyBool Get call
似乎还可以,因为我在“MyBool”上绑定了2个单选按钮
现在,如果我选择“MyBool为false”单选按钮:
在产量方面:
MyBool Set call + RaiseProperty
MyBool Get call
MyBool Get call
还不错
现在,如果我关闭NewView并再次打开它,然后选择“MyBool为false”单选按钮,则输出为:
MyBool Set call + RaiseProperty
MyBool Get call
MyBool Get call
MyBool Get call
MyBool Get call
然后,输出再次是:
MyBool Set call + RaiseProperty
MyBool Get call
MyBool Get call
MyBool Get call
MyBool Get call
MyBool Get call
MyBool Get call
再一次:
MyBool Set call + RaiseProperty
MyBool Get call
MyBool Get call
MyBool Get call
MyBool Get call
MyBool Get call
MyBool Get call
MyBool Get call
MyBool Get call
等等
如您所见,在我的财产上“获取”呼叫,增加每个团队我重新打开视图我找到了一个解决方案,但这是一个丑陋的解决方案
正如我在评论中所说,我并不是唯一一个参与我的项目的人,解决方案涉及到其他我无法编辑的项目。因此,我不能简单地抑制“ViewModelLocator”
因此,要解决我的问题,请在我的ViewModelLocator中,在我的ViewModels属性中,而不是执行以下操作:
public NewViewModel NewView
{
get
{
var vm = ServiceLocator.Current.GetInstance<NewViewModel>();
vm.Initialize();
return vm;
}
}
public NewView模型NewView
{
得到
{
var vm=ServiceLocator.Current.GetInstance();
vm.Initialize();
返回虚拟机;
}
}
我这样做:
public NewViewModel NewView
{
get
{
SimpleIoc.Default.Unregister<NewViewModel>();
SimpleIoc.Default.Register<NewViewModel>(true);
var vm = ServiceLocator.Current.GetInstance<NewViewModel>();
vm.Initialize();
return vm;
}
}
public NewView模型NewView
{
得到
{
SimpleIoc.Default.Unregister();
SimpleIoc.Default.Register(true);
var vm=ServiceLocator.Current.GetInstance();
vm.Initialize();
返回虚拟机;
}
}
每次调用ViewModel时(因此当我打开视图时),该模型都会先取消注册,然后再注册。它强制重新创建ViewModel,因此所有对PropertyChanged的订阅都将重置
我不会将此解决方案设置为好的解决方案,因为我认为此解决方案不是很漂亮。但是它可以工作,而且使用的内存似乎没有提高。我找到了另一个解决方案,一个比我发布的第一个解决方案更漂亮的解决方案
在我的ViewModelLocator中,我删除了所有viewmodel属性。
我创建了这个静态函数:
public static T GetViewModelInstance<T>(Window w)
{
var uniqueKey = System.Guid.NewGuid().ToString();
T VMInstance = ServiceLocator.Current.GetInstance<T>(uniqueKey);
w.Closed += (sender, args) => SimpleIoc.Default.Unregister(uniqueKey);
return VMInstance;
}
公共静态T GetViewModelInstance(窗口w)
{
var uniqueKey=System.Guid.NewGuid().ToString();
T VMInstance=ServiceLocator.Current.GetInstance(uniqueKey);
w、 Closed+=(发送方,参数)=>SimpleIoc.Default.Unregister(uniqueKey);
返回VMInstance;
}
因此,如您所见,我不返回ViewModel,而是返回它的一个新实例(带有uniqueKey标记)。
我在调用view Closed事件上注册,以注销创建的VM实例
我不再在xaml中定义DataContext,而是在xaml.cs中,在构造函数中,我将DataContext设置为:
DataContext = ViewModelLocator.GetViewModelInstance<NewViewModel>(this);
DataContext=ViewModelLocator.GetViewModelInstance(此);
它工作得很好。请分享您的问题的代码示例。如果在
ShowDialog()
之后设置v.Owner=null
,会怎么样?您使用的是哪个版本的mvvmlight,解决方案的目标是什么框架?您的命令使用语句,它的末尾是否有WPF?我添加了一些代码。我使用nuget包“MvvmLightLibs v5.3.0”和应用程序目标.NET Framework 4.5.2。是的,这是一个WPF应用程序,而不是使用viewmodellocator。尝试使MyViewModel成为myview的私有成员,。在xaml中实例化它。你的问题解决了吗?