2010-03-05 113 views
4

我有一个可绑定到列表框的地址的ObservableCollection。然后在ItemTemplate中,我使用{Binding。}绑定到当前地址记录。这导致我的地址显示使用我已设置格式化地址的ToString方法。一切都很好,除非我更新单个地址记录上的属性,UI中的列表不会更新。添加/删除列表确实更新UI(使用ObservableCollection行为)。如果我直接绑定到UI更新地址上的属性(使用Address对象的INotifyPropertyChanged行为)。数据绑定在使用{绑定}或{绑定}时未更新

我的问题是,有没有办法通知用户界面对整个对象所做的更改,以便我仍然可以使用此语法,或者是否需要在我的地址类型上放置DisplayText属性ToString方法并绑定到那个?仅供参考,这是一个MVVM架构,所以我没有直接在ListBox上调用Refresh的奢侈。

感谢您的任何帮助/想法。

<ListBox x:Name="AddressList" ItemsSource="{Binding Addresses}" Background="Transparent" BorderBrush="Transparent" 
    Width="200" HorizontalAlignment="Left"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
     <StackPanel> 
      <TextBlock Text="{Binding .}" /> 
     </StackPanel> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
    </ListBox> 

回答

3

当您绑定到Address对象本身时,对象本身 - 即它的标识 - 不会改变,即使它的属性有效。因此WPF不知道在这种情况下刷新绑定。

所以是的,你需要绑定到通知属性(或属性)而不是整个对象。正如你所说,做到这一点的一种方法是创建一个DisplayText属性,并在每次影响显示文本的内容发生更改时为该属性引发PropertyChanged事件。另一种方法是在水平方向的StackPanel中使用多个TextBlocks,每个TextBlocks绑定到一个特定的属性,例如

<StackPanel Orientation="Horizontal"> 
    <TextBlock Text="{Binding HouseNumber}" /> 
    <TextBlock Text=", " /> 
    <TextBlock Text="{Binding Street}" /> 
    <TextBlock Text=", " /> 
    <TextBlock Text="{Binding City}" /> 
</StackPanel> 

第二种方法的优点是,它使您可以灵活地在用户界面中更改地址的显示方式,例如,多行,格式化等;缺点是如果你有条件逻辑,它会变得复杂。一个可选的平面数字或第二个地址线。

+0

这很有道理。虽然我认为我会坚持显示文本属性路由,因为我们需要支持美国和外国地址以及第二行,如您所述。为了在WPF方面取得成功,可能需要一个转换器类。对我来说,让实体类保持集中更有意义。如有必要,调用者可以将所有单个字段覆盖它。 – Mark 2010-03-07 15:32:28

2

我试图重现问题并成功。

我激活了step-in-.NET调试选项,并看到如果绑定中的路径为空,WPF不会侦听INotifyPropertyChanged。

在列表框中反映的变化是取代ObservableCollection中的整个对象。这会触发INotifyCollectionChanged和Replace操作。

但在您的情况下,这可能是不可接受的。它可能更像是一种黑客,而不是一个固定的解决方案。

我会认真考虑有一个DataTemplate的地址。在那里你应该绑定到你需要的确切属性(这将创建INotifyPropertyChanged的监听器)。它比ToString()更灵活,并且您可能会遇到需要ToString()为非UI内容做些事情的情况,这会造成冲突。说实话,ToString并不是真正用于UI的东西。