C# 如何以最优雅的方式将数据绑定到ItemsControl中的特定项属性?
场景:一个列表视图被数据绑定到一个C# 如何以最优雅的方式将数据绑定到ItemsControl中的特定项属性?,c#,.net,wpf,silverlight,C#,.net,Wpf,Silverlight,场景:一个列表视图被数据绑定到一个可观察集合,并通过一个自定义项目模板显示它的项目。CustomClass只包含三个字符串属性和一个布尔属性,并且已经在它的四个属性中的每一个上实现了inotifypropertychange。ListView的自定义ItemTemplate对三个字符串属性具有单向绑定,对boolean属性具有双向绑定,并将其显示为复选框 问题:我正在寻找一种最优雅的方式(就WPF而言)来显示该列表视图中使用文本块的所有选中项的计数,或者换句话说,在该集合中,所有布尔属性设置为t
可观察集合
,并通过一个自定义项目模板显示它的项目。CustomClass
只包含三个字符串属性和一个布尔属性,并且已经在它的四个属性中的每一个上实现了inotifypropertychange。ListView的自定义ItemTemplate对三个字符串属性具有单向绑定,对boolean属性具有双向绑定,并将其显示为复选框
问题:我正在寻找一种最优雅的方式(就WPF而言)来显示该列表视图中使用文本块的所有选中项的计数,或者换句话说,在该集合中,所有布尔属性设置为true
的项。如果某个ListView项目被选中/取消选中,我希望该文本块立即更新显示的计数。我知道有(相当)丑陋的方法通过代码隐藏和事件处理来实现这一点,但我想知道是否有一种聪明的方法可以完全用XAML和神秘的数据绑定语法来实现这一点
编辑:正如示例/说明:ListView显示100个项目,90个项目的布尔属性设置为
true
,因此TextBlock将显示“90”。如果用户通过复选框取消选中另一个项目,并因此通过双向绑定将其属性设置为false
,则文本块应更新为“89”。如果它是一个简单的ASP.NET表单,我将考虑使用JQuery对列表框中的选定项目进行计数。在WPF中,这可能仍然是一个可行的选择:
var count = 0;
$('#multiItemListBox :selected').each(count++);
将此代码插入ListBox的OnChange事件的JS事件处理程序。您必须知道在客户端得到的HTML中实际会调用什么样的列表框,我不确定WPF是如何将它们混合在一起的,或者如何将正确的引用粘贴到服务器端XAML中。您可以使用转换器构建一个包含选中项计数的字符串
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
}
公共密封类CountToString转换器:System.Windows.Data.IValueConverter{
#区域转换器成员
公共对象转换(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性){
ObservableCollection项目=作为ObservableCollection的价值;
整数计数=0;
foreach(项目中的var项目){
如果(项目已检查){
计数++;
}
}
返回计数+项目数;
}
公共对象转换回(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性){
抛出新的NotImplementedException();
}
#端区
}
将TextBox的Text属性绑定到集合
<TextBox Text={Binding Items, Converter={StaticResource countToStringConverter}}/>
更新:
仅当属性项触发PropertyChanged事件(如果集合已更改)时,此绑定才起作用。我个人可能会在我的ViewModel中执行此操作。订阅ObservaleCollection中的项上更改的属性,然后在布尔属性更改时向ViewModel上更改的Count属性发送信号。在您看来,只需绑定到Count属性。感谢我得到的所有答案,这些都是适用的解决方案,但不幸的是,这并不是我想要实现的。这就是我现在解决问题的方法: 我在包含TextBlock的窗口上实现了DependencyProperty:
public static readonly DependencyProperty ActiveItemCountProperty =
DependencyProperty.Register("ActiveItemCount", typeof(int), typeof(CustomControl), new UIPropertyMetadata(0));
在ListView项目的DataTemplate上,复选框为Click事件注册了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);
}
private void复选框\单击(对象发送者,路由目标)
{
ObservableCollection sourceCol=listView.DataContext作为ObservableCollection;
if(sourceCol!=null)
ActiveItemCount=sourceCol.Count(x=>x.Active);
}
显然,TextBlock只是绑定到此DependencyProperty的数据:
<TextBlock Text="{Binding Path=ActiveItemCount, ElementName=ControlRoot}" />
ControlRoot是窗口的名称。谢谢您的回答,但我不只是想显示所选项目的计数(我可以简单地绑定到SelectedItems.count),而是要显示将特定属性(在本例中为布尔属性)设置为特定值的所有项目的计数。例如:ListView有100个项目,其中90个项目的布尔属性设置为true-因此TextBlock将显示“90”。如果我取消选中一个项目,它会显示89个,但是ListView本身仍然有所有100个初始项目。谢谢你的回答。的确,扩展ViewModel是一种很好的方法。但我有点想避免这种情况,因为我使用的是非常简单的数据结构。。。我一直在考虑在DataTemplate上实现一个EventSetter,以从代码隐藏中处理每个项的复选框的选中事件。。。但我真正想做的是对ListView的ItemsSource或ObjectDataProvider进行某种直接数据绑定,它利用LINQ语句或类似的东西…@naacal。提供一个包含检查项计数的附加属性比使用EventSetter、checked Event等更容易。@Jehof:这可能确实很容易,但我必须实现另一个类,以便为我提供此属性。现在,CustomClass并不打算成为ViewModel的一部分,这也是我最初问题的全部目的——是否有任何方法可以在XAML中做到这一点,而无需实现更多代码,只需将这个小数据绑定到TextBlock。主/详细实现中的数据绑定语法使用特殊斜杠(/)语法绑定到当前项,这让我想到,可能有一种方法可以在ItemsSource和bool属性上执行类似的操作