C# MvvmLight:如何取消订阅;RaisePropertychanged";事件

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

我在使用MvvmLight的WPF应用程序中遇到问题

我的申请:

  • 我有一个带有菜单的主视图,每个菜单项都将打开一个新视图(每个菜单项都不同)
  • 每个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中实例化它。你的问题解决了吗?