简体   繁体   English

具有CollectionViewSources组和HierarchicalDataTemplate的设计时树视图绑定

[英]Design-time treeview binding with CollectionViewSources groups and HierarchicalDataTemplate

I'd like to get sample data to appear in my Treeview during design time. 我想让样本数据在设计时显示在Treeview中。 My Treeview contains nested Treeviews and CollectionViewSources. 我的树视图包含嵌套的树视图和CollectionViewSources。

I'd like to find out how to get the nested Treeviews to show (only the first of 3 levels of nodes show currently). 我想了解如何显示嵌套的树视图(当前仅显示3个级别的节点中的第一个)。

About the Treeview 关于树视图

Here's what I've figured out so far: 到目前为止,这是我所发现的:

My Treeview contains Hierarchical data (Object States (eg "Ready") > Date (ie "8/8/16") > Name (ie "Apples"), but I can only get one. 我的树形视图包含层次结构数据(对象状态(例如,“就绪”)>日期(即,“ 8/8/16”)>名称(即,“苹果”),但是我只能得到一个。

The Treeview is backed by: 树视图的支持者:

  • ObjectTreeviewViewModel (a ObservableCollection) ObjectTreeviewViewModel(一个ObservableCollection)
  • CollectionViewSource to group by StateDisplay (+ sorting) CollectionViewSource按StateDisplay分组(+排序)
  • Another CollectionViewSource to group by ObjectDateDisplay 另一个由ObjectDateDisplay分组的CollectionViewSource

Current Status 当前状态

The ObjectTreeview only shows one level of nodes at design time, when I'm expecting 3 levels of nodes. 当我期望3个级别的节点时,ObjectTreeview在设计时仅显示一个级别的节点。

Treeview(WPF)在设计时仅显示1级节点-应该显示3级

My Stack 我的堆栈

I'm building a WPF application on .net 4.5, using Visual Studio 2015. 我正在使用Visual Studio 2015在.net 4.5上构建WPF应用程序。

Code

XAML 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 Resources 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>

Code-Behind 代码隐藏

    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);
                    }
            }
    }

I found a workaround to my problem. 我找到了解决问题的方法。

The Issue 问题

The issue was with the inner CollectionViewSource (the one that controlled the middle of 3 nodes). 问题出在内部的CollectionViewSource(控制三个节点中间的那个)。 Only the outer CollectionViewSource was showing its node. 仅外部CollectionViewSource显示其节点。

The design time binding couldn't use the same Path=Items that the run time was using. 设计时绑定不能使用与运行时相同的Path=Items

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

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

</CollectionViewSource>

The Solution 解决方案

Update the d:DesignSource to load from the XAML example file (the same one we use above) with Source=ObjectTreeviewDesignTimeData.xaml . 更新d:DesignSource,以使用Source=ObjectTreeviewDesignTimeData.xaml从XAML示例文件(与上面使用的文件相同) Source=ObjectTreeviewDesignTimeData.xaml

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

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

    </CollectionViewSource>

After setting the d:DesignSource and re-building, the 3 levels of nodes started appearing at design time. 设置d:DesignSource并重新构建后,在设计时开始出现3个级别的节点。 I confirmed that the issue with the design-time binding was with the inner CollectionViewSource. 我确认设计时绑定的问题在于内部CollectionViewSource。

A Sufficient Workaround 充分的解决方法

By binding to the same dictionary in the outer and inner CollectionViewSources, redundant data is generated. 通过绑定到外部和内部CollectionViewSources中的同一字典,可以生成冗余数据。 (The dictionary is loaded multiple times, for each sub-treeview.) However, this is OK, as I'm in the Designer Mode and I simply need placeholder data. (对于每个子树视图,字典都会多次加载。)但是,这没关系,因为我处于设计器模式,我只需要占位符数据。

A better solution would be to find a way to get the inner CVS d:DesignerSource="{BETTER_SOLUTION_HERE}" part to work using the same collection as the outer CVS. 更好的解决方案是找到一种方法,以使内部CVS d:DesignerSource="{BETTER_SOLUTION_HERE}"部分与外部CVS使用相同的集合来工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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