繁体   English   中英

WPF 多绑定到 ObservableCollection 的一部分

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM