场景: ListView是DataBound到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'。
答案 0 :(得分:2)
您可以使用转换器构建一个包含已检查项目数的字符串
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-Property绑定到Collection。
<TextBox Text={Binding Items, Converter={StaticResource countToStringConverter}}/>
<强>更新强> 仅当属性项触发PropertyChanged-Event时,如果更改了Collection,此Binding才有效。
答案 1 :(得分:2)
我个人可能会在我的ViewModel中执行此操作。订阅ObservableCollection中项目更改的属性,然后每当布尔属性更改时,都会在ViewModel上发送更改的Count属性。在您的视图中,只需绑定到Count属性。
答案 2 :(得分:0)
如果它是一个简单的ASP.NET表单,我会看看使用JQuery来计算ListBox中的选定项。这可能仍然是WPF中可行的选择:
var count = 0;
$('#multiItemListBox :selected').each(count++);
将此代码插入到ListBox的OnChange事件的JS事件处理程序中。您将不得不知道客户端获取的HTML实际上会调用ListBox,我不确定WPF如何将它们混淆或如何将正确的引用粘贴到服务器端XAML中。
答案 3 :(得分:0)
感谢我所得到的所有答案,这些都是适用的解决方案,但不幸的是,这并不是我试图实现的目标。所以这就是我现在解决问题的方法:
我在包含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作为Window的名称。