代码之家  ›  专栏  ›  技术社区  ›  vc 74

MVVM viewmodel属性触发更新

  •  0
  • vc 74  · 技术社区  · 14 年前

    (我没有使用任何工具箱)。

    我的页面包含一个带有两个组合框的部分。在其中一个组合框中选择一个项目将触发更新组合框下方可见网格的搜索。

    • 如果viewmodel中的reset函数更新了backing字段,UI将不会反映更改,因为不会调用RaisePropertyChanged。
    • 如果viewmodel中的reset函数更新属性,UI将反映更改,但网格将更新两次:将第一个属性重置为null时,第二个属性也将更新

    /// <summary>Selected user.</summary>
    public User SelectedUser
    {
        get { return _selectedUser; }
        set
        {
            _selectedUser = value;
            RaisePropertyChanged("SelectedUser");
    
            UpdateProducts();
        }
    }
    
    /// <summary>Selected product category.</summary>
    public ProductCategory SelectedProductCategory
    {
        get { return _selectedProductCategory; }
        set
        {
            _selectedProductCategory = value;
            RaisePropertyChanged("SelectedProductCategory");
    
            UpdateProducts();
        }
    }
    
    // Reset option 1
    public void Reset()
    {
        _selectedUser = null;
        _selectedProductCategory = null;
        _products = null;
    }
    
    // Reset option 2
    public void Reset()
    {
        SelectedUser = null;
        SelectedProductCategory = null;
        // No need to update Products which has already been updated twice...
    }
    
    3 回复  |  直到 14 年前
        1
  •  1
  •   Daniel Paull    14 年前

    在许多框架中,包括WPF,这确实让我感到不安。您需要的是延迟对更改通知的响应的一些概念,以便用户永远不会看到中间状态。但是,您不能改变WPF响应通知的方式,因此您所能做的最好的方法是将通知延迟到“尘埃落定”之后。在您的情况下,您需要在发送任何通知之前更改这两个备份字段。您的重置方法可以将此想法编码如下:

    public void Reset()
    {
        _selectedUser = null;
        _selectedProductCategory = null;
        _products = null;
    
        RaisePropertyChanged("SelectedUser");
        RaisePropertyChanged("SelectedProductCategory");
    }
    

    在我看来,WPF同步更新显示以响应更改通知的方式是完全错误的。他们的DependencyProperty系统让他们有机会只将依赖项标记为脏项,并在以后执行重新计算。

    我使用标记为脏的异步重新计算的思想作为您在这个问题中注意到的问题的一般解决方案,这些天我无法想象没有它的编程。遗憾的是,更多的框架不能以这种方式工作。

        2
  •  1
  •   Thomas Levesque    14 年前

    你可以养一只 PropertyChanged 更新备份字段后所有属性的事件:

    RaisePropertyChanged(String.Empty);
    
        3
  •  0
  •   Tokk    14 年前

    如果使用backing字段,则必须调用

    RaisePropertyChanged("SelectedUser");
    RaisePropertyChanged("SelectedProductCategory");