WPF、MVVM和ComboBox:当更改为不同的viewmodel时,ComboBox会使绑定到SelectedItem的属性为空

WPF、MVVM和ComboBox:当更改为不同的viewmodel时,ComboBox会使绑定到SelectedItem的属性为空,wpf,mvvm,combobox,Wpf,Mvvm,Combobox,我有一个窗口,它使用DataTemplates在ContentPresenter中根据内容属性的类型显示不同的UserControl(视图),该属性绑定到保存当前viewmodel的属性。通过这种方式,通过使用事件更改viewmodel属性,我可以方便地进行所需的基本后退/前进导航 创建新的viewmodel时,将向其传递对当前viewmodel的引用。返回到旧的viewmodel实例对于复选框控件很好,但对于我创建的包含TextBlock和ComboBox的UserControl则不行 问题是

我有一个窗口,它使用DataTemplates在ContentPresenter中根据内容属性的类型显示不同的UserControl(视图),该属性绑定到保存当前viewmodel的属性。通过这种方式,通过使用事件更改viewmodel属性,我可以方便地进行所需的基本后退/前进导航

创建新的viewmodel时,将向其传递对当前viewmodel的引用。返回到旧的viewmodel实例对于复选框控件很好,但对于我创建的包含TextBlock和ComboBox的UserControl则不行

问题是,当包含组合框的视图被卸载时,组合框的ItemsSource被置空,这会触发它清除其SelectedItem/Text属性,这些属性出于某种原因仍然绑定到我的viewmodel,从而清除它存储的数据。我不知道如何在适当的时候手动解除绑定。(同样,复选框工作正常。)

我读到其他用户也有同样的问题。对于它们,更改ItemsSource和SelectedItem/Text绑定的声明顺序,以便在前者之前放置后者的属性,从而解决问题。然而,就我而言,情况并非如此。其他人也通过忽略null/empty值解决了这个问题,但这在我的情况下不起作用

我可以通过将感兴趣的数据复制到一个单独的对象并从中重新加载来解决这个问题,但是我需要添加代码来触发重新加载数据=需要维护更多的数据链接代码

我还可以避免使用DataTemplates,并在codebehind中手动添加UserControls,这将允许我在删除UserControls之前中断数据绑定。但这与MVVM的观点背道而驰

我不会修改我的非MVVM UserControl来处理它包含的ComboBox上的任何事件来解决这个问题


更新:


我把问题缩小了一点。我重构了代码,以便它手动创建并添加viewmodel所基于的ViewUserControl。现在,只有当我将view UserControl的DataContext设置为null时,问题才会出现。如果我只是替换视图而不删除引用,它将不再删除有问题的值。这是一个可用的解决方法,还是会产生内存泄漏之类的问题?

这是WPF早期版本中已知的由事件跳转引起的错误。对于.NET4.0中的选择器派生控件,它是固定的


有关更多详细信息,请参阅本文:

我已经解决了这个问题,在我的基本viewmodel类中添加了属性Active和相应的Activate()/Deactivate()方法,并在交换viewmodels时根据需要调用这些方法。这非常适合我的应用程序。当然,我仍然愿意接受其他建议。

也许可以“敞开心扉”寻求更简单的解决方案。。。如果我理解你的问题,这和我们过去的问题很相似。在我们的例子中,我们只是假设在绑定属性访问时不可能将特定值设置为null,因此我们稍微调整了相应的ViewModel属性:

public MyItem SelectedItem {
  get {
    return Model.MyItem;
  }
  set {
     if (value != null) {
       // Set and notify if not null
       Model.MyItem = value;
       OnPropertyChanged("SelectedItem");
     }
     else // just notify when trying to set to null
       OnPropertyChanged("SelectedItem");
  }
}
通过调用
OnPropertyChanged(..)
insead,我们能够阻止任何将值设置为
null
的尝试,现有值被UI调用。如果需要将值设置为
null
,则必须提供一个单独的属性来允许该设置

不确定这是否适用于您的问题。 祝你好运

更新

哦,我看到这可能描述了与“其他人也通过忽略空/空值解决了问题”相同的方法,这在您的情况下似乎不起作用。但我不明白为什么它不应该。

很高兴知道它已经修复,但这对我没有多大好处,因为我的公司没有VS2010的任何许可证:/我在家里的VS2010上试用过它,但仍然遇到同样的问题,即使是针对.NET 4。添加一个附加属性来设置null/empty也可以。虽然当OnPropertyChanged()试图将值设置为null时,为什么仍然调用它?我不确定在哪种情况下它会真正起作用,但再次调用
OnPropertyChanged
背后的想法是,它告诉UI使用getter再次更新-在那里它将重置为未触及的前一个值。(例如,在Silverlight中,我们发现有些控件会重新加载getter以测试设置是否成功,而有些则不会-UI状态和ViewModel状态可能会不同步)