項目更改時更新 WPF 列表
我有一個 WPF 列錶框,並且添加了一些“FooBar”對像作為項目(通過程式碼)。FooBars 不是 WPF 對象,只是具有覆蓋 ToString() 函式的啞類。
現在,當我更改影響 ToString 的屬性時,我希望更新 ListBox。
- 我怎樣才能做到這一點“又快又髒”(比如重新粉刷)。
- 依賴屬性是解決這個問題的方法嗎?
- 是否值得/總是建議為我的 FooBars 創建一個 wpf 包裝類?
謝謝…
您的類型應該實現
INotifyPropertyChanged,以便集合可以檢測到更改。正如 Sam 所說,string.Empty作為論點傳遞。您還需要讓
ListBox的數據源成為提供更改通知的集合。這是通過INotifyCollectionChanged介面(或非 WPFIBindingList介面)完成的。當然,您需要在
INotifyCollectionChanged成員INotifyPropertyChanged項之一觸發其事件時觸發該介面。值得慶幸的是,框架中有一些類型可以為您提供這種邏輯。可能最合適的一個是ObservableCollection<T>。如果您將您的綁定ListBox到一個,ObservableCollection<FooBar>那麼事件連結將自動發生。在相關說明中,您不必使用
ToString方法來讓 WPF 以您想要的方式呈現對象。你可以使用DataTemplate這樣的:<ListBox x:Name="listBox1"> <ListBox.Resources> <DataTemplate DataType="{x:Type local:FooBar}"> <TextBlock Text="{Binding Path=Property}"/> </DataTemplate> </ListBox.Resources> </ListBox>通過這種方式,您可以控制對象所屬的對象的呈現方式——在 XAML 中。
編輯 1我注意到您的評論是您正在使用該
ListBox.Items集合作為您的集合。這不會進行所需的綁定。你最好做這樣的事情:var collection = new ObservableCollection<FooBar>(); collection.Add(fooBar1); _listBox.ItemsSource = collection;我沒有檢查該程式碼的編譯準確性,但你明白了要點。
編輯 2使用
DataTemplate我上面給出的(我編輯它以適應你的程式碼)解決了這個問題。
PropertyChanged觸發不會導致列表項更新似乎很奇怪,但是使用該ToString方法並不是 WPF 的預期工作方式。使用此 DataTemplate,UI 可以正確綁定到確切的屬性。
不久前我在這裡問了一個關於在WPF 綁定中進行字元串格式化的問題。您可能會發現它很有幫助。
編輯 3我很困惑為什麼這仍然不適合你。這是我正在使用的視窗的完整原始碼。
後面的程式碼:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows; namespace StackOverflow.ListBoxBindingExample { public partial class Window1 { private readonly FooBar _fooBar; public Window1() { InitializeComponent(); _fooBar = new FooBar("Original value"); listBox1.ItemsSource = new ObservableCollection<FooBar> { _fooBar }; } private void button1_Click(object sender, RoutedEventArgs e) { _fooBar.Property = "Changed value"; } } public sealed class FooBar : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string m_Property; public FooBar(string initval) { m_Property = initval; } public string Property { get { return m_Property; } set { m_Property = value; OnPropertyChanged("Property"); } } private void OnPropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } }XAML:
<Window x:Class="StackOverflow.ListBoxBindingExample.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:StackOverflow.ListBoxBindingExample" Title="Window1" Height="300" Width="300"> <DockPanel LastChildFill="True"> <Button Click="button1_Click" DockPanel.Dock="Top">Click Me!</Button> <ListBox x:Name="listBox1"> <ListBox.Resources> <DataTemplate DataType="{x:Type local:FooBar}"> <TextBlock Text="{Binding Path=Property}"/> </DataTemplate> </ListBox.Resources> </ListBox> </DockPanel> </Window>