Как DataBind к определенным свойствам элемента в ItemsControl наиболее элегантным способом? - PullRequest
2 голосов
/ 09 сентября 2010

Сценарий: ListView имеет привязку DataBound к ObservableCollection<CustomClass> и отображает свои элементы через пользовательский шаблон ItemTemplate. CustomClass просто содержит три строковых свойства и одно логическое свойство, и уже имеет INotifyPropertyChanged, реализованный в каждом из его четырех свойств. Пользовательский ItemTemplate ListView имеет односторонние привязки для трех строковых свойств и двустороннюю привязку для логического свойства, отображая его как CheckBox.

Проблема: Я ищу самый элегантный (с точки зрения WPF) способ отображения количества всех проверенных элементов в этом ListView с использованием TextBlock - или, другими словами, всех элементов, которые имеют их логическое свойство установлено в true в этой коллекции. Я хочу, чтобы TextBlock немедленно обновлял отображаемое количество, если один из элементов ListView отмечен / не отмечен. Я знаю, что есть (довольно) некрасивые способы достичь этого с помощью кода и обработки событий, но я хотел бы знать, есть ли умный способ сделать это, возможно, полностью в XAML с загадочным синтаксисом DataBinding.

Редактировать: Так же, как пример / пояснение: ListView отображает 100 элементов, для 90 элементов их логическое свойство имеет значение true, поэтому TextBlock будет отображать '90'. Если пользователь снимает флажок еще с одного элемента через его CheckBox и, следовательно, устанавливает его свойство на false с помощью двухсторонней привязки, TextBlock должен обновиться до '89'.

Ответы [ 4 ]

2 голосов
/ 10 сентября 2010

Вы можете использовать конвертер для создания строки с количеством отмеченных элементов

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 к коллекции.

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

ОБНОВЛЕНИЕ: Эта привязка работает только в том случае, если элементы свойства запускают событие PropertyChanged, если коллекция изменена.

2 голосов
/ 10 сентября 2010

Лично я, вероятно, выполнил бы это в моей ViewModel. Подпишитесь на свойство, измененное для элементов в ObservableCollection, и затем сообщайте об изменении свойства Count в ViewModel при каждом изменении логического свойства. По вашему мнению, просто привяжите к свойству Count.

0 голосов
/ 15 сентября 2010

Спасибо за все ответы, которые я получил, это были все применимые решения, но, к сожалению, это не совсем то, чего я пытался достичь.Вот как я решил эту проблему:

Я реализовал свойство DependencyProperty в окне, содержащем TextBlock:

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

На шаблоне данных для элементов ListView, зарегистрированный CheckBoxEventHandler для Click-Event:

<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.

0 голосов
/ 09 сентября 2010

Если бы это была простая форма ASP.NET, я бы посмотрел на использование JQuery для подсчета выбранных элементов в ListBox.Это может быть жизнеспособной опцией в WPF:

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

Подключите этот код к обработчику событий JS для события OnChange объекта ListBox.Вам нужно будет знать, как на самом деле будет вызываться ListBox в HTML-коде, который получает клиент, и я не уверен, как WPF объединяет их или как вставить правильную ссылку в XAML на стороне сервера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...