尝试将HierarchicalDataTemplate的ItemsSource属性绑定到CollectionViewSource(以执行分组和过滤)

时间:2009-05-12 21:14:33

标签: treeview

问题:我们想将HierarchicalDataTemplate的ItemsSource属性绑定到CollectionViewSource,以执行分组和过滤。

背景:我们正在处理的原始问题与过滤TreeView有关。具体来说,我们发现使用CollectionViewSource进行过滤工作但导致TreeView节点崩溃。这可能是因为View的Refresh函数重新生成其对象列表,导致TreeView重新生成其节点,从而导致原始节点的扩展状态丢失。我们通过编写一个类似于CollectionViewSource的类来解决这个问题,但是通过编辑对象列表来保留View,这样当它由于过滤而发生变化时,相关的TreeView节点就不会被销毁。

这对我们来说非常有效,我们希望在TreeView的更深层次上使用它,让我们回到我们的问题。目前,我们有一个如下所示的HierarchicalDataTemplate:

<HierarchicalDataTemplate

    x:Key="tableTemplate"

    ItemsSource="{Binding Path=DataItems}"

    ItemTemplateSelector="{StaticResource tableGroupsTemplateSelector}"

    >

相反,我们希望它的行为如下:

<HierarchicalDataTemplate

    x:Key="tableTemplate"

    ItemTemplateSelector="{StaticResource tableGroupsTemplateSelector}"

    >

    <HierarchicalDataTemplate.ItemsSource>

        <Binding>

            <Binding.Source>

                <CollectionViewSource

                    Source="{Binding Path=DataItems}"

                    />

            </Binding.Source>

        </Binding>

    </HierarchicalDataTemplate.ItemsSource>

不幸的是,这种方法似乎不起作用。据我们所知,CVS中的绑定永远不会发生;没有引起绑定错误;我们尝试连接转换器并设置断点,但断点从未被击中。我们还尝试了各种其他解决方案,包括:使用RelativeSource,将CollectionViewSource移动到模板的Resources中,并将TreeViewItem合并到模板中。但是,没有任何效果。

顺便说一句,我确实意识到ViewModel方法可以启用过滤。但是,我正处于开发周期的某个地方,我无法进行这种类型的更改,因此我正在寻找替代方案,例如CollectionViewSource方法。

您可以给予任何帮助。

谢谢,

-Craig

1 个答案:

答案 0 :(得分:4)

在我的应用程序中,我发现实现树视图过滤的最简单方法是将可见性绑定到列出的对象上的属性。

这种方法可能对你不起作用,但如果你想在这里尝试,那就是我所做的一个例子。

在树视图资源中添加样式触发器。您可以将触发器绑定到显示的对象上的任何属性,如果要添加一些逻辑来检查项目并确定是否应该显示它,则可以添加值转换器。

<TreeView.Resources>
   <Style TargetType="TreeViewItem">
         <Style.Triggers>
               <DataTrigger Binding="{Binding Path=Display}" Value="False">
                    <Setter Property="Visibility"  Value="Collapsed"/>
               </DataTrigger>
         </Style.Triggers>
   </Style>
</TreeView.Resources>

如果“Display”属性为false,则触发器将折叠treeView项。

为避免向对象添加“显示”属性,您可以执行以下操作:

 public class PositionVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {

            int positions = (int) value;
            if (positions > 0)
                return true;
            return false;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new System.NotSupportedException();
        }
    }

在TreeView Style绑定中添加值转换器:

<TreeView.Resources>
   <Style TargetType="TreeViewItem">
         <Style.Triggers>
               <DataTrigger Value="False">
                    <Binding Path="Positions">
                        <Binding.Converter>
                            <local:PositionVisibilityConverter/>
                        </Binding.Converter>
                    </Binding>
                    <Setter Property="Visibility"  Value="Collapsed"/>
               </DataTrigger>
         </Style.Triggers>
   </Style>
</TreeView.Resources>

如果要检查整个对象,则无需指定路径。

这种方法似乎最适合我,试一试。