[英]WPF MultiBinding to part of ObservableCollection
我需要将 TextBlock 的文本设置为“名称(不具有 null 属性的项目数)”之类的内容。 现在,我正在使用 ItemsSource.Count 使用整个集合的项目数来执行此操作。
<TextBlock x:Name="textBlockHeader" >
<TextBlock.Text>
<MultiBinding Converter="{StaticResource headerCreator}" x:Name="multiBinder">
<Binding ElementName="trackingTable" Path="Name" />
<Binding ElementName="trackingsGrid" Path="ItemsSource.Count" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
为此,我正在使用 IMultiValueConverter:
internal class HeaderCreator : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Based on this xaml
////<Binding ElementName="trackingTable" Path="Name" /> values[0]
////<Binding ElementName="trackingsGrid" Path="ItemsSource.Count" /> values[1]
return values[0] + " (" + values[1] + ")";
}
trackingsGrid 是下面定义的 DataGrid(此处未显示代码),绑定到具有 TrackingData 对象的集合。 TrackingData 有一个名为 Tracking 的属性。 我只需要计算 ObservableCollection 中具有此属性的项目,而不是 null。 我怎样才能做到这一点?
public class TrackingData : INotifyPropertyChanged
{
public Model.ITracking Tracking { get; set; }
...
}
提前致谢。
将此逻辑(...项目在具有此属性的 ObservableCollection 中具有此属性不为空)在您的 ViewModel 中并绑定到此属性。
就我个人而言,我会将它添加到 ViewModel 中,因为它是高度定制的。
话虽如此,您可以通过一些小的调整来完成这项工作。 首先,将您的第二个绑定从ItemsSource.Count
更改为ItemsSource
。 这将导致IMultiValueConverter
中的values[1]
成为整个集合。
完成此操作后,您的转换器可能会更改,因此您报告:
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Based on this xaml
////<Binding ElementName="trackingTable" Path="Name" /> values[0]
////<Binding ElementName="trackingsGrid" Path="ItemsSource" /> values[1]
IEnumerable<TrackingData> tracking = values[1] as IEnumerable<TrackingData>;
if(tracking == null)
return values[0] + " (0)"; // Put some reasonable value here?
return values[0] + " (" + tracking.Where(t => t.Tracking != null).Count() + ")";
}
我建议避免使用MultiBinding
,除非它是完全必要的。 在必要时很难划清界限,但通常您知道什么时候没有其他选择可以实现所需的行为,或者替代实现需要付出巨大的努力。 我的直觉告诉我, MultiBinding
不仅在性能方面效率较低,而且还更难阅读、测试和维护。
也就是说,您可以通过 ViewModel 中的属性(如@polishchuk 建议的那样)或绑定到整个视图 model 和基于视图 model 返回格式化字符串的单个转换器来实现所需的行为。 在两个选项中,如果您不需要高级文本格式,我更喜欢第一个,否则,我更喜欢第二个。
正如一些人指出的那样,我会将这个逻辑移到 ViewModel 中。 这是一种简单的方法,不需要您附加一堆事件处理程序并编写自定义逻辑:
在 ViewModel 中实现这一点的一种简单方法是创建一个ICollectionView
来包装您的源集合并对其应用过滤器以仅包含属性不是 null 的值
IList<T> source = ...
ListCollectionView customView = new ListCollectionView(source);
customView.Filter = obj => ((TrackingData)obj).Tracking != null;
然后你可以通过你的 ViewModel 公开这个 ICollectionView 作为一个属性,比如TrackedItems
然后在 XAML 中,您可以将数据绑定到TrackedItems.Count
。 随着您的 TrackingData object 属性更改, ICollectionView
将保持同步
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.