【问题标题】:WPF, MVVM, and ComboBox: when changing to a different viewmodel, the ComboBox nulls the property bound to SelectedItemWPF、MVVM 和 ComboBox:当更改为不同的视图模型时,ComboBox 会将绑定到 SelectedItem 的属性设为空
【发布时间】:2011-03-16 23:48:14
【问题描述】:

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

创建新视图模型时,会传递对当前视图模型的引用。回到旧的视图模型实例对于 CheckBox 控件可以正常工作,但对于我制作的包含 TextBlock 和 ComboBox 的 UserControl 则不行。

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

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

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

我还可以避免使用 DataTemplates 并在代码隐藏中手动添加 UserControl,这样我就可以在删除 UserControl 之前中断数据绑定。但这与 MVVM 的观点背道而驰。

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


更新:

我已经稍微缩小了这个问题的范围。我重构了代码,以便它根据已设置的视图模型手动创建和添加视图 UserControl。现在仅当我将视图 UserControl 的 DataContext 设置为 null 时才会出现此问题。如果我只是在不删除引用的情况下替换视图,它就不再删除有问题的值。这是一个可用的解决方法,还是会产生内存泄漏等问题?

【问题讨论】:

    标签: wpf mvvm combobox


    【解决方案1】:

    也许会为更简单的解决方案“敞开心扉”......如果我理解您的问题,它类似于我们过去遇到的问题。在我们的例子中,我们只是假设在被绑定属性访问时无法将特定值设置为 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");
      }
    }
    

    使用这些经过调整的属性,我们能够阻止任何将值设置为null 的尝试,通过调用OnPropertyChanged(..) insead,UI 调用现有值。如果需要能够将值设置为 null,则必须提供一个单独的属性来允许这样做。

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

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

    【讨论】:

    • 添加一个额外的属性来设置 null/empty 会起作用。虽然为什么在尝试将值设置为 null 时仍然调用 OnPropertyChanged()?
    • 我不确定在哪种情况下它会真正起作用,但再次调用 OnPropertyChanged 背后的想法是,它告诉 UI 使用 getter 再次更新 - 它将被重置为未触及的先前值。 (例如在 Silverlight 中,我们发现有些控件会重新加载 getter 以测试设置是否成功,而有些则不会 - UI 状态和 ViewModel 状态可能不同步)
    【解决方案2】:

    这是 WPF 早期版本中由事件跨越引起的已知错误。它已针对 .NET 4.0 中的 Selector 派生控件进行了修复。

    有关详细信息,请参阅此博客文章:http://blogs.interknowlogy.com/2011/03/09/event-leapfrogging/

    【讨论】:

    • 很高兴知道它已得到修复,但这对我没有多大好处,因为我的公司没有任何 VS2010 许可证。 ://
    • 我在家里的 VS2010 上尝试过,但仍然遇到同样的问题,即使针对 .NET 4 也是如此。
    【解决方案3】:

    我通过将属性 Active 和相应的 Activate()/Deactivate() 方法添加到我的基本视图模型类中解决了这个问题,并在换出视图模型时适当地调用这些方法。这非常适合我的应用程序。当然,我仍然愿意接受其他建议。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      • 1970-01-01
      • 2012-06-19
      • 2010-10-24
      • 2014-12-08
      • 1970-01-01
      相关资源
      最近更新 更多