2010-01-03 83 views
2

此代碼點點幫我介紹我的問題:我可以通過LINQ綁定更新UI嗎?

public class Car 
{ 
    ... 
} 

public class CarQueue : ObservableCollection<Car> 
{ 
    public IEnumerable Brands 
    { 
     get { return (from Car c in this.Items select c.Brand).Distinct(); } 
    } 
} 

好了,現在我有一個綁定到DataGrid CarQueue類的一個實例。當我將一個Car對象添加到隊列中時,datagrid本身會更新,但我也有一個綁定到'Brands'屬性的列表框,該屬性不會更新。下面是一個簡單的代碼序列來解釋:

CarQueue cq = new CarQueue(); 
DataGrid1.ItemsSource = cq; 
ListBox1.ItemsSource = cq.Brands; // all above done during window load 
... 
Car c; 
cq.Add(c); // datagrid updates, but not listbox 

是否列表框中沒有更新,因爲它必然要與動態LINQ查詢的屬性?

我試圖在繼承INotifyPropertyChanged的,並添加一個新的事件處理程序CollectionChanged事件(在我的CarQueue構造函數)的另一件事:在事件處理程序

this.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(CarQueue_CollectionChanged); 

然後:

void CarQueue_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
{ 
    PropertyChanged(this, new PropertyChangedEventArgs("Brands")); 
} 

這也沒有工作。那麼有誰知道問題是什麼?謝謝

回答

5

這裏有幾個問題。

Brands屬性是一個由LINQ在需要時建立的序列。 WPF在初始綁定期間只會要求它:它無法知道如果再次詢問它會得到不同的答案,所以它不會。爲了讓WPF跟蹤品牌集合的變化,您需要將品牌作爲一個集合進行展示,並在該集合上實施INotifyCollectionChanged - 例如,通過將Brands設爲ObservableCollection。一種方法是使用Bindable LINQ

作爲替代方案,您可以使用第二種方法爲品牌籌集PropertyChanged事件。然而,爲了這個工作,你必須綁定 ItemsSource to Brands。 (目前,你正在分配它,這意味着WPF忘記了收集來自哪裏,並保留其私人副本的值。)要做到這一點,要麼使用XAML中的{Binding}標記擴展:

<ListBox ItemsSource="{Binding Brands}" /> <!-- assumes DataContext is cq --> 

或使用BindingOperations.SetBinding:

BindingOperations.SetBinding(ListBox1, ListBox.ItemsSourceProperty, 
    new Binding("Brands") { Source = cq }); 
+0

完美。我只是在XAML中進行了綁定,它可以工作。可綁定的LINQ看起來對我來說會非常有用,所以謝謝。 – Adam 2010-01-03 04:38:38

+1

對於記錄,我注意到Bindable LINQ似乎沒有更新一段時間,但還有另一個名爲Continuous LINQ的項目似乎正在做一些相同的事情。還沒有嘗試過這一點,但是如果你想要一試,你可以從http://www.codeplex.com/clinq得到它。 – itowlson 2010-01-03 04:44:00

相關問題