使用CollectionViewSources组和HierarchicalDataTemplate进行设计时树视图绑定

时间:2016-08-08 16:37:27

标签: c# .net wpf visual-studio xaml

我希望在设计时将样本数据显示在我的Treeview中。我的Treeview包含嵌套的Treeviews和CollectionViewSources。

我想了解如何显示嵌套的Treeviews(目前仅显示3个节点级别中的第一个)。

关于Treeview

这是我到目前为止所知道的:

我的Treeview包含分层数据(对象状态(例如" Ready")> Date(即" 8/8/16")> Name(即" Apples& #34;),但我只能得到一个。

Treeview支持:

  • ObjectTreeviewViewModel(一个ObservableCollection)
  • CollectionViewSource按StateDisplay(+排序)
  • 分组
  • 另一个由ObjectDateDisplay分组的CollectionViewSource

当前状态

ObjectTreeview仅在设计时显示一个级别的节点,当我期待3个级别的节点时。

Treeview (WPF) only shows 1 level of nodes in design time- should show 3

我的筹码

我正在使用Visual Studio 2015在.net 4.5上构建WPF应用程序。

代码

XAML

    <UserControl x:Class="myproject.app.views.MainWindow.ObjectTreeview"
                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                             mc:Ignorable="d" 
                             d:DesignHeight="300" d:DesignWidth="300" 
                             DataContext="{Binding RelativeSource={RelativeSource Self}}"
                             >

            <UserControl.Resources>

                    <ResourceDictionary>
                            <ResourceDictionary.MergedDictionaries>
                                    <ResourceDictionary Source="../../resources/MainWindow/ObjectTreeviewResources.xaml"></ResourceDictionary>
                            </ResourceDictionary.MergedDictionaries>
                    </ResourceDictionary>

            </UserControl.Resources>

            <TreeView x:Name="Treeview" 
                                        ItemsSource="{Binding Source={StaticResource ObjectStateCollectionViewSource}, Path=Groups}"
                                        ItemTemplate="{Binding Source={StaticResource ObjectStateTemplate}}">
            </TreeView>

    </UserControl>

XAML资源

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                                            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                                            xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
                                            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                                            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                                            xmlns:pf="clr-namespace:System.ComponentModel;assembly=PresentationFramework"
                                            xmlns:mainWindow="clr-namespace:myproject.app.viewmodels.MainWindow"
                                            mc:Ignorable="d">

            <!-- I.e. Level-3 Node (i.e. Leaf nodes) -->
            <DataTemplate x:Key="ObjectTreeviewNode">
                    <TextBlock Text="{Binding ObjectNameDisplay}"/>
            </DataTemplate>


            <!-- Initial Grouping: Group by object states -->
            <CollectionViewSource x:Key="ObjectStateCollectionViewSource" 
                                                        Source="{Binding Path=ObjectTreeviewViewModel.TreeviewCollection}"
                                                        d:DesignSource="{d:DesignData Source=ObjectTreeviewDesignTimeData.xaml}"
                                                        >
                    <CollectionViewSource.GroupDescriptions>
                            <PropertyGroupDescription PropertyName="StateDisplay"/>
                    </CollectionViewSource.GroupDescriptions>
                    <CollectionViewSource.SortDescriptions>
                            <componentModel:SortDescription PropertyName="StateEnum" />
                            <componentModel:SortDescription PropertyName="ObjectDate" />
                            <componentModel:SortDescription PropertyName="ObjectNameDisplay" />
                    </CollectionViewSource.SortDescriptions>
            </CollectionViewSource>

            <!-- I.e. Level-2 Node (i.e. mid-nodes) -->
            <HierarchicalDataTemplate x:Key="ObjectDateTemplate">
                    <TreeView BorderThickness="0">
                            <TreeViewItem Header="{Binding Path=Name}" 
                                                        ItemsSource="{Binding Path=Items}"
                                                        d:DataContext="{Binding Path=Items}"
                                                        ItemTemplate="{StaticResource ResourceKey=ObjectTreeviewNode}"
                                                        IsExpanded="True"/>
                    </TreeView>
            </HierarchicalDataTemplate>

            <!-- I.e. Level-1 Node (i.e. Root nodes) -->
            <HierarchicalDataTemplate x:Key="ObjectStateTemplate" >
                    <TreeView BorderThickness="0">

                            <TreeView.Resources>

                                    <!-- Sub-grouping: Group by object dates (This needs to be nested in this Treeview.Resources) -->
                                    <CollectionViewSource x:Key="ObjectDateCollectionViewSource"
                                                                                Source="{Binding Path=Items}"
                                                                                d:DesignSource="{Binding Path=Items}"
                                                                                > 

                                            <CollectionViewSource.GroupDescriptions>
                                                    <PropertyGroupDescription PropertyName="ObjectDateDisplay"/>
                                            </CollectionViewSource.GroupDescriptions>

                                    </CollectionViewSource>

                                    <!-- [This and all children] Hide the light-grey inactive background -->
                                    <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Transparent" />

                            </TreeView.Resources>

                            <TreeViewItem Header="{Binding Path=Name}" 
                                                        ItemsSource="{Binding Source={StaticResource ObjectDateCollectionViewSource}, Path=Groups}"
                                                        ItemTemplate="{StaticResource ObjectDateTemplate}"
                                                        IsExpanded="True"/>

                    </TreeView>
            </HierarchicalDataTemplate>
    </ResourceDictionary>

代码隐藏

    using System.Windows.Controls;
    using myproject.app.viewmodels.MainWindow;
    using myproject.lib.enumerations;

    namespace myproject.app.views.MainWindow
    {
            /// <summary>
            /// Interaction logic for ObjectTreeview.xaml
            /// </summary>
            public partial class ObjectTreeview : UserControl
            {
                    public ObjectTreeviewViewModel ObjectTreeviewViewModel { get; private set; } = new ObjectTreeviewViewModel(); // this is a ObservableCollection<ObjectViewModel>

                    public ObjectTreeview()
                    {
                            InitializeComponent();
                    }

                    /// <summary>
                    ///     Load object for an objectStateGroup (a set of ObjectStates) into the collection that backs the treeview.
                    /// </summary>
                    /// <param name="objectStateGroup">The objectStateGroupsEnum to load.</param>
                    public void LoadObjectStateGroup(objectStateGroupsEnum objectStateGroup)
                    {
                            ObjectTreeviewViewModel.LoadobjectStateGroup(objectStateGroup);
                    }
            }
    }

1 个答案:

答案 0 :(得分:0)

我找到了解决问题的方法。

问题

问题在于内部CollectionViewSource(控制3个节点中间的那个)。只有外部CollectionViewSource显示其节点。

设计时绑定无法使用运行时使用的Path=Items

<CollectionViewSource x:Key="ObjectDateCollectionViewSource"
                      Source="{Binding Path=Items}"
                      d:DesignSource="{Binding Path=Items}"> 

                <CollectionViewSource.GroupDescriptions>
                                <PropertyGroupDescription PropertyName="ObjectDateDisplay"/>
                </CollectionViewSource.GroupDescriptions>

</CollectionViewSource>

解决方案

使用Source=ObjectTreeviewDesignTimeData.xaml更新d:DesignSource以从XAML示例文件(我们上面使用的那个)加载。

    <CollectionViewSource x:Key="ObjectDateCollectionViewSource"
                          Source="{Binding Path=Items}"
                          d:DesignSource="{d:DesignData Source=ObjectTreeviewDesignTimeData.xaml}"> 

            <CollectionViewSource.GroupDescriptions>
                    <PropertyGroupDescription PropertyName="ObjectDateDisplay"/>
            </CollectionViewSource.GroupDescriptions>

    </CollectionViewSource>

设置d:DesignSource并重新构建后,3个级别的节点在设计时开始出现。我确认设计时绑定的问题在于内部的CollectionViewSource。

充分的解决方法

通过绑定到外部和内部CollectionViewSources中的相同字典,可以生成冗余数据。 (对于每个子树视图,字典会被多次加载。)但是,这很好,因为我在Designer模式中只需要占位符数据。

更好的解决方案是找到一种方法让内部CVS d:DesignerSource="{BETTER_SOLUTION_HERE}"部分使用与外部CVS相同的集合。