簡體   English   中英

如何以最優雅的方式將數據綁定到ItemsControl中的特定項目屬性?

[英]How to DataBind to specific item properties in an ItemsControl in the most elegant way?

場景:一個ListView被DataBound ObservableCollection<CustomClass>到一個ObservableCollection<CustomClass>並通過一個自定義的ItemTemplate顯示它的項目。 CustomClass僅包含三個字符串屬性和一個布爾屬性,並且已經在其四個屬性的每一個上實現了INotifyPropertyChanged。 ListView的自定義ItemTemplate在三個字符串屬性上具有單向綁定,在布爾屬性上具有雙向綁定,將其顯示為CheckBox。

問題:我正在尋找最優雅的方式(就WPF而言),以使用TextBlock顯示該ListView中所有已檢查項目的計數-換句話說,在該集合中所有布爾屬性設置為true的項目。 如果希望ListView項之一被選中/取消選中,我希望TextBlock立即更新顯示的計數。 我知道有一些(相當)丑陋的方法可以通過代碼和事件處理來實現,但是我想知道是否有一種聰明的方法可以完全在XAML中使用奧秘的DataBinding語法來做到這一點。

編輯:僅作為示例/說明:ListView顯示100個項目,其中90個項目的布爾屬性設置為true ,因此TextBlock將顯示“ 90”。 如果用戶通過其CheckBox取消選中了另一個項目,因此通過雙向綁定將其屬性設置為false ,則TextBlock應該更新為“ 89”。

您可以使用Converter來建立一個帶有已檢查項目計數的字符串

public sealed class CountToStringConverter : System.Windows.Data.IValueConverter {
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
        ObservableCollection<CustomClass> items = value as ObservableCollection<CustomClass>;

        int count = 0;

        foreach (var item in items) {
            if (item.IsChecked) {
                count++;
            }
        }

        return count + " Items";
    }

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

    #endregion
}

將文本框的文本屬性綁定到集合。

<TextBox Text={Binding Items, Converter={StaticResource countToStringConverter}}/>

更新:此綁定僅在屬性項觸發PropertyChanged-Event且集合發生更改時才起作用。

我個人可能會在ViewModel中執行此操作。 訂閱在ObservableCollection中的項目上更改的屬性,然后在布爾屬性更改時向ViewModel發出Count屬性更改的信號。 在您看來,只需綁定到Count屬性。

如果它是簡單的ASP.NET表單,那么我將看一下使用JQuery對ListBox中的選定項目進行計數。 在WPF中,這仍然是可行的選擇:

var count = 0;
$('#multiItemListBox :selected').each(count++);

將此代碼插入到ListBox的OnChange事件的JS事件處理程序中。 您將必須知道客戶端獲取的HTML中實際上將調用ListBox的內容,而且我不確定WPF如何將它們混搭起來或如何將正確的引用粘貼到服務器端XAML中。

感謝您提供的所有答案,這些都是適用的解決方案,但不幸的是,並不是我嘗試達到的目標。 所以這就是我現在解決問題的方式:

我已經在包含TextBlock的窗口上實現了DependencyProperty:

public static readonly DependencyProperty ActiveItemCountProperty =
        DependencyProperty.Register("ActiveItemCount", typeof(int), typeof(CustomControl), new UIPropertyMetadata(0));

在ListView項的DataTemplate上,CheckBox為Click-Event注冊了一個EventHandler:

<CheckBox IsChecked="{Binding Active, Mode=TwoWay}" Click="CheckBox_Click" />

后面代碼中的事件處理程序如下所示:

    private void CheckBox_Click(object sender, RoutedEventArgs e)
    {
        ObservableCollection<CustomClass> sourceCol = listView.DataContext as ObservableCollection<CustomClass>;
        if (sourceCol != null)
            ActiveItemCount = sourceCol.Count(x => x.Active);
    }

顯然,TextBlock只是綁定到此DependencyProperty的數據:

<TextBlock Text="{Binding Path=ActiveItemCount, ElementName=ControlRoot}" />

使用ControlRoot作為窗口的名稱。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM