2015-07-11 97 views
0

我有以下XAML:爲什麼ListBox綁定到IEnumerable更新?

<Window x:Class="ListBoxTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:ListBoxTest" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <local:Model /> 
    </Window.DataContext> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <ListBox ItemsSource="{Binding Items}" Grid.Row="0"/> 
     <Button Content="Add" Click="Button_Click" Grid.Row="1" Margin="5"/> 
    </Grid> 
</Window> 

,爲Model類,它被放入主窗口的DataContext以下代碼:

public class Model : INotifyPropertyChanged 
{ 
    public Model() 
    { 
     items = new Dictionary<int, string>(); 
    } 

    public void AddItem() 
    { 
     items.Add(items.Count, items.Count.ToString()); 

     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs("Items")); 
    } 

    private Dictionary<int, string> items; 
    public IEnumerable<string> Items { get { return items.Values; } } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

和主窗口中的代碼:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     var model = this.DataContext as Model; 
     model.AddItem(); 
    } 
} 

按下按鈕時,列表中的內容爲否正在更新。

然而,當我改變Items屬性的getter這樣:

public IEnumerable<string> Items { get { return items.Values.ToList(); } } 

它開始工作。

然後,當我註釋掉髮送了PropertyChanged事件的部分時,它會停止再次工作,這表明事件正在正確發送。

因此,如果列表收到事件,爲什麼不能在第一個版本中正確更新它的內容,而不需要撥打ToList

+3

你有沒有考慮過使用ObservableCollection? – heltonbiker

+0

@heltonbiker它有嚴重的缺點 - 像缺少「AddRange」,也沒有其他可能性執行批量更新,這不會導致每個添加項目的更新。另外,我有一本字典不是一個普通的列表。 – BartoszKP

+0

@BartoszKP有可用的可觀察字典的實現(只需搜索ObservableDictionary)。您可以將ListBox的ItemsSource直接綁定到ObservableDictionary,並將ListBox項目(在ItemTemplate中)綁定到字典條目的'Value'屬性。 – Clemens

回答

2

提高Items屬性的PropertyChanged事件僅在屬性值實際發生更改時纔有效。在引發事件時,WPF綁定基礎結構注意到屬性getter返回的集合實例與之前相同,並且不會更新綁定目標。

但是,當您返回items.Values.ToList()時,每次都創建一個新的集合實例,並更新綁定目標。

+0

似乎我完全誤解了'PropertyChanged'是什麼:)這完全有道理,在我正在閱讀有關該主題的內容中。謝謝! – BartoszKP

+0

我不知道它是否正好相關,但有時會調用'NotifyPropertyChanged(null)'(使用null作爲參數而不是屬性名稱),屏幕上的_every_屬性會更新。它爲我過去解決了一些問題。 – heltonbiker

+2

@heltonbiker即使您通知所有屬性(而不是特定屬性)的更改,也不會更新綁定目標,因爲源集合實際上並未發生更改。 – Clemens

相關問題