2012-10-30 64 views
3

我设计了一个MVVM WPF应用程序,并有一个ViewModel,它具有一个Customer类型的SelectedCustomer属性。这个对象有一个叫做SummaryDetails的属性,它的类型为ObservableCollection,它可以一行一行地渲染成一个ListView。WPF MVVM可观察集合不更新GUI

为此,我在ViewModel上创建了一个名为CustomerSummaryDetails的单独属性,它包含一个get,它返回包含在我上面提到的客户中的集合。

在XAML中,我已将ItemsSource绑定到CustomerSummaryDetails属性。

这是因为我没有必要绑定到SelectedCustomer.SummaryDetails是不干净。

SelectedCustomer属性有一个get和一个set方法,并且该集合为OTHER属性CustomerSummaryDetails调用OnPropertyChanged,让XAML知道底层集合已更改和更新。

虽然所有正确的事件被调用,但问题是,当我更新集合中的项目时,它不反映在GUI上。我已经介入并调用SelectedCustomer的set方法,然后按照预期的方式跟随OnPropertyChanged(“CustomerSummaryDetails”)调用进入CustomerSummaryDetails属性的“get”方法。我已经深入研究了返回集合的值,并且列表中的值是已更新的值,但是没有任何结果反映在GUI上,所以我感到困惑,因为看起来GUI正在调用get方法来更新它在OnPropertyChanged()调用上,但它不是可视化的反映。

更新 - 代码中包含了

对不起,不包括代码,我认为这将是容易只是形容,但这里是主要的视图模型性能

public CustomerSummaryViewModel SelectedCustomer 
{ 
    get { return _selectedCustomer; } 
    set 
    { 
     _selectedCustomer = value; 
     OnPropertyChanged("CustomerSummaryDetails"); 
    } 
} 

public ObservableCollection<RbcUICustomerSummary> CustomerSummaryDetails 
{ 
    get { return _selectedCustomer.SummaryDetails; } 
} 

public ItemSummaryViewModel SelectedItem 
{ 
    get { return _selectedItem; } 
    set 
    { 
     _selectedItem = value; 
     OnPropertyChanged("SelectedItem"); 
    } 
} 

XAML下面

<ListView x:Name="lvCustomerSummary" Margin="10,10,10,10" Background="#F4F8FB" ItemsSource="{Binding CustomerSummaryDetails}" MouseDoubleClick="lvCustomerSummary_MouseDoubleClick" ItemContainerStyle="{StaticResource myHeaderStyleColor}" VirtualizingStackPanel.IsVirtualizing="False" VirtualizingStackPanel.VirtualizationMode="Recycling"> 
      <ListView.View> 
      <GridView ColumnHeaderContainerStyle="{StaticResource myHeaderStyle}"> 
        <GridView.Columns> 
        <GridViewColumn Header="" > 
         <GridViewColumn.CellTemplate> 
          <DataTemplate > 
           <Grid> 
            <Image Source="{z:ImageStaticResource {Binding IconSelect}}" Width="20" Height="20" /> 
           </Grid> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
        <GridViewColumn Width="200" Header="SubCustType" DisplayMemberBinding="{Binding SubCustType}" > 
        </GridViewColumn> 
        <GridViewColumn Width="200" Header="SubCustValue" DisplayMemberBinding="{Binding SubCustValue}"> 
        </GridViewColumn> 
        <GridViewColumn Header="" > 
         <GridViewColumn.CellTemplate> 
          <DataTemplate > 
           <Grid> 
            <Image Source="{z:ImageStaticResource {Binding IconFlag}}" Width="20" Height="20" /> 
           </Grid> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
       </GridView.Columns> 
      </GridView> 
     </ListView.View> 
    </ListView> 

最后是实际更新的更新器方法

private void DisplayCustomerComment(string commentEnt) 
{    
    if (_queueViewModel.SelectedCustomer == null) return; 
     var selCust = _queueViewModel.SelectedCustomer; 

    foreach (var t in selCust.SummaryDetails 
     .Where(t => t.SubCustType == AppString.CustomerSummary.Comment)) 
    { 
     t.SubCustValue = commentEnt; 
     break; 
    } 

    _queueViewModel.SelectedCustomer = selCust; 
} 
+0

虽然你说类型“客户”,什么样的数据类型是“客户”...它是一个强类型的类对象,数据表的数据行等? – DRapp

+0

您的CustomerSummaryDetails属性的签名是什么?我建议发布一些源代码而不是描述它可能也更容易。 :-) – AlSki

+0

您的绑定模式设置为? –

回答

16

您并未修改ObservableCollection本身(如添加/删除项目),而是修改了INSIDE集合中的项目。 ObservableCollection负责通知其自己的更改,而不是与其项目相关的更改。您应该在SubCustValue的设置器中通知属性更改(“SubCustValue”)。

更改没有反映在UI中,因为当您NotifyPropertyChange()整个集合而不是单个项目的个别属性时,WPF会检测到它实际上是同一个实例(对同一个集合的同一对象引用)像以前一样,所以没有任何改变。

+0

作为一个便笺,为什么你要收集第一个项目并破解?替换FirstOrDefault()或其他东西并删除foreach。 –

+0

你能否解释一下,如果我在里面有简单的集合(没有可观察的),我怎样才能更新\ rebind数据。哪种方式最好?谢谢。 –

+0

@СергійКислий这是一个单独的问题,你宁愿发表一个新的问题。 –