2010-03-05 151 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的東西。