2010-09-22 128 views
0

我开始为我的一个Silverlight应用程序实现MVVM。 (我没有使用任何工具包)。MVVM viewmodel属性触发更新

我的页面包含有两个组合框的部分。选择其中一个组合中的某个项目会触发一个搜索,用于更新组合框下可见的网格。

每个组合的选定项目都绑定到我的视图模型中的一个属性。这些属性的setter会引发INotifyPropertyChanged属性更改并自动更新绑定到网格的数据。

一切都很好,直到我需要添加一个重置按钮,其目的是重置搜索参数即:每个组合框不应该指示任何项目和网格应该是空的。

  • 如果viewmodel中的重置函数更新后备字段,则UI将不会反映更改,因为不会调用RaisePropertyChanged。
  • 如果视图模型复位功能更新的属性,用户界面将反映这些更改,但网格将被更新两次:正在重置第一属性时为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... 
} 

回答

1

这是真的让我在很多框架,WPF包括。您需要的是延迟响应更改通知的一些概念,以便用户永远不会看到中间状态。但是,您无法更改WPF对您的通知的响应方式,所以您可以做的最好的做法是延迟您的通知,直到“尘埃落定之后”。就你而言,你需要在发送任何通知之前更改两个支持字段。

public void Reset() 
{ 
    _selectedUser = null; 
    _selectedProductCategory = null; 
    _products = null; 

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

在我看来,顺便WPF同步更新显示在应对变化的通知,是完全错误的:你的复位方法如下编码这个想法。他们的DependencyProperty系统为他们提供了一个机会,只需将依赖项标记为脏,并在稍后进行重新计算。

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

+0

感谢您的回答,我同意你的意见。它不仅在理论上是错误的,如果我碰巧改变属性名称,重构将无法更新关联的RaisePropertyChanged,如果它们位于一个地方(属性设置器),但对我来说似乎没有问题危险的是他们在其他地方可用 – 2010-09-22 09:21:11

+0

不要让我开始使用字符串的属性更改通知...哦,如此脆弱和低效。你会认为微软定义核心API的人会更聪明一些。 – 2010-09-22 09:26:05

0

如果使用支持字段,你将不得不调用

RaisePropertyChanged("SelectedUser"); 
RaisePropertyChanged("SelectedProductCategory"); 
在reset()方法

+0

谢谢您的回答,那就是我试图避免:重复RaisePropertyChanged同一属性。我想在理论上我不应该,但正如你所建议我可能没有选择... – 2010-09-22 09:04:55

1

您更新后备字段后,可以提高一个PropertyChanged事件的所有属性:

RaisePropertyChanged(String.Empty); 
+0

谢谢。这当然会刷新所有的控制,即使那些不关心这些变化的控制。我的整个UI不会“眨眼”? – 2010-09-22 09:27:22

+0

是的,它会刷新与视图模型绑定的所有内容。但我怀疑你会看到它“眨眼”... – 2010-09-22 09:45:29

相关问题