我需要将TextBlock的Text设置为“Name(具有非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; }
...
}
提前致谢。
答案 0 :(得分:2)
在ViewModel中将此逻辑(...项目在ObservableCollection中具有此属性为非null)并绑定到此属性。
答案 1 :(得分:1)
就个人而言,我会将其添加到ViewModel中,因为它是如此高度自定义。
话虽如此,你可以通过一些小的调整来完成这项工作。首先,将您的第二个绑定从ItemsSource.Count
更改为ItemsSource
。这会导致values[1]
内的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" /> 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() + ")";
}
答案 2 :(得分:0)
我建议避免使用MultiBinding
,除非它是完全必要的。在必要时很难划清界限,但通常你知道什么时候没有其他选择可以达到预期的行为,或者替代实施需要付出很大的努力。我的直觉告诉我MultiBinding
不仅效率低下,而且阅读,测试和维护也更难。
那就是说你可以通过ViewModel中的属性(如@polishchuk建议的那样)实现所需的行为,或绑定到整个视图模型和单个转换器,它返回基于视图模型的格式化字符串。在两个选项中,如果您不需要高级文本格式,我会更喜欢第一个选项,否则第二个选项。
答案 3 :(得分:0)
正如一些人指出的那样,我会把这个逻辑移到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对象属性发生变化时,ICollectionView
将保持同步