2013-02-06 38 views
3

我有一個的ObservableCollection,我需要綁定2個標籤,首先顯示的收集和第二項中的計數顯示值的總和。WPF數據綁定使用的ObservableCollection [標籤

首先標籤綁定到收藏count屬性和第二標籤直接綁定到的ObservableCollection與轉換器計算總所有項目的

XAML看起來像這樣

<Grid> 
    <ListBox Name="itemList" ItemsSource="{Binding DataList}"/> 
    <Label Name="lblcount" Content="{Binding DataList.Count}" /> 
    <Label Name="lblTotal" Content="{Binding DataList, Converter={StaticResource calculateTotalConvertor}" /> 
</Grid> 

我的VM具有收藏這樣

ObservableCollection<int> data = new ObservableCollection<int>(); 

    public ObservableCollection<int> DataList 
    { 
     get { return data; } 
     set { data = value; } 
    } 

我的轉換代碼是

public class CalculateTotalConvertor : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     ObservableCollection<int> collection = value as ObservableCollection<int>; 

     return collection.Sum(); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

問題是在DataList控件添加新項目,項目的ListView和標籤顯示計數被更新,但「lblTotal」犯規得到與總數更新。

基本上如何強制您具有約束力的ObservableCollection變化進行評估?它如何直接爲ListView或DataGrid工作,但不能用於標籤?

我知道這個問題可以通過在虛擬機創建一個屬性來顯示總並提高性能變化時,採集得到更新來解決,但有什麼比這更好的解決方案呢?

中,當然這是我的簡單實際問題的形式,我沒有訪問視圖模型和集合,它是一個第三方控制。我正在創建一個包裝器用戶控件,並且對視圖的內部集合有一個相對綁定。

+0

你試過'set {data = value; RaisePropertyChanged( 「數據」); ''? –

+1

老實說,我會提供一個完全符合你想要的屬性,並處理VM中的邏輯。使用轉換器是件奇怪的事情,我儘量避免使用它。想想看,一個轉換器應該將一個值轉換爲另一個值,你將一個列表轉換爲一個數字。如果初始值被更新,則轉換器會被再次調用,它不是你的情況,它保持不變,只是其內部狀態發生變化。使用你的虛擬機,爲視圖提供和預處理數據是視圖模型的主要目的。 – dowhilefor

+0

@dowhilefor我同意你...我想知道DataGrid如何更新集合更改,以及我是否可以在此處執行同樣的操作。我的實際用例很多,很複雜。我編輯了這個問題。 – Ankit

回答

2

其他的答案正確地解釋爲什麼它沒有更新。迫使它來更新您可以將轉換器更改爲IMultiValueConverter

public class CalculateTotalConvertor : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     ObservableCollection<int> collection = values.FirstOrDefault() as ObservableCollection<int>; 

     return collection.Sum(); 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

然後更改您綁定到一個MultiBinding這也拉動計數:

<Label Name="lblTotal"> 
    <Label.Content> 
     <MultiBinding Converter="{StaticResource calculateTotalConvertor}"> 
      <Binding Path="DataList"/> 
      <Binding Path="DataList.Count"/> 
     </MultiBinding> 
    </Label.Content> 
</Label> 

現在第二個結合將通知綁定需要在添加或刪除項目時進行更新,但您可以忽略計數值而不使用它。

+0

很酷。這解決了我的問題。謝謝 ! – Ankit

0

它沒有更新,因爲它綁定到DataListDataList沒有改變,計數標籤更新,因爲它綁定到DataList.Count,當一個項目被添加到列表中被更新。

我認爲更新Sum標籤的唯一方法是通知用戶界面DataList已更改,但這會導致ListBox重新綁定列表,並且它的性能將比僅僅具有更高的成本您的型號屬性更新Sum

所以我認爲最好的辦法是使用你的模型屬性使用ObservableCollectionsCollectionChangedEvent或caculate的總和,增加了項目列表

0

它適用於ListViewDataGrid邏輯,因爲這些是ItemsControl s表示聽ObservableCollectionCollectionChangedEvent,當集合本身是通過添加或刪除項目改變了提高。

在另一方面的LabelContentControl僅監聽PropertyChangedEvent。由於在插入之後,您的DataList與之前的ObservableCollection相同,因此不會引發任何事件。

剛纔看到您的編輯:

如果要創建一個包裝的控制,給第三方控制的姓名和控件的代碼掛鉤到其內收集的CollectionChangedEvent後面。這樣你仍然可以將更新通知推送到你的包裝視圖。

去與額外的屬性,它會爲您節省轉換器上的一些代碼。從後面的代碼:

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    ObservableCollection<int> _list = new ObservableCollection<int>(); 
    int _sum = 0; 
    Random rnd = new Random(); 

    public MainWindow() 
    { 
     DataList = new ObservableCollection<int>(); 
     DataList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(DataList_CollectionChanged); 
     DataContext = this; 
     InitializeComponent(); 
    } 

    void DataList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     switch (e.Action) 
     { 
      case NotifyCollectionChangedAction.Add: 
       foreach (object number in e.NewItems) 
        _sum += (int)number; 
       break; 
      case NotifyCollectionChangedAction.Remove: 
       foreach (object number in e.OldItems) 
        _sum -= (int)number; 
       break; 
     } 
     OnNotifyPropertyChanged("Sum"); 
    } 

    public int Sum { get { return _sum; } } 
    public ObservableCollection<int> DataList { get; set; } 

    private void Add_Btn_Click(object sender, RoutedEventArgs e) 
    { 
     DataList.Add(rnd.Next(0, 256)); 
    } 

    private void Remove_Btn_Click(object sender, RoutedEventArgs e) 
    { 
     if (DataList.Count == 0) 
      return; 

     DataList.RemoveAt(DataList.Count - 1); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    void OnNotifyPropertyChanged(string property) 
    { 
     if (PropertyChanged == null) 
      return; 

     PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    } 
} 
相關問題