将 HierarcicalDataTemplates 与 TreeViewItem 控件模板结合使用
我在弄清楚如何模板化以下 TreeView 项目布局时遇到一些困难:
我有几个项目,SearchList ,其中包含 Search 的集合,其中包含 DataSet 的集合(有点像,但这不是重点)。我遇到的困难是按照我想要的方式设置每个节点级别的样式。我正在使用 MVVM,并且 TreeViews ItemsSource 属性设置为 SearchListViewModels 的 ObservableCollection,而该集合又包含我的对象一直到对象树。
我可以成功设置 SearchList HierarchicalDataTemplate 的样式以正确显示它们。我困惑的地方是 SearchTerm 节点样式。我希望数据集在 SearchTerm 内容区域右侧的包装面板或统一网格(我尚未决定)中表示。我已经修改了 TreeViewItem 控件模板以按照我认为的方式运行),但是如果我在搜索 HierarchicalDataTemplate 的 ItemContainerStyle 属性中设置它,它不会执行任何操作。显示的只是搜索的内容。
我的更改后的 TreeViewItem 模板
<Style TargetType="{x:Type TreeViewItem}" x:Key="AlteredTreeViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
MinWidth="19" />
<ColumnDefinition Width="0.414*" />
<ColumnDefinition Width="0.586*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Bd" HorizontalAlignment="Stretch"
Grid.Column="1" Grid.ColumnSpan="1" Background="#7F058956">
<ContentPresenter x:Name="PART_Header" Margin="10,0" />
</Border>
<WrapPanel x:Name="ItemsHost"
Grid.Column="2" IsItemsHost="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我的搜索分层数据模板
<HierarchicalDataTemplate DataType="{x:Type local:SearchViewModel}" ItemsSource="{Binding MySearch.Custodians}" ItemContainerStyle="{StaticResource AlteredTreeViewItem}">
<TextBlock Text="{Binding MySearch.SearchName}" Foreground="Black" FontFamily="Arial" FontSize="16"/>
</HierarchicalDataTemplate>
当然可以使用不同的样式并且使子项布局不同吗?如何才能实现这一目标?
I am having some difficulty figuring out how to template the following TreeView item layout:
I have several items, SearchList, which contains a collection of Search, which contains a collection of DataSet (sort of, but that is beside the point). What I am having difficulty with is styling each node level the way I want. I am using MVVM, and the TreeViews ItemsSource property is set to an ObservableCollection of SearchListViewModels which in turn contain my objects all the way down the object tree.
I can successfully style the SearchList HierarchicalDataTemplate to display them correctly. Where I get hung up is on SearchTerm nodes styling. I want the DataSets to be represented in a wrap panel or uniform grid (I haven't decided yet) to the right of the SearchTerm content area. I have modified a TreeViewItem control template to behave this way I think), however if I set it in the ItemContainerStyle property of the Search HierarchicalDataTemplate, it does nothing. All that gets displayed is the content for the Search.
My Altered TreeViewItem Template
<Style TargetType="{x:Type TreeViewItem}" x:Key="AlteredTreeViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
MinWidth="19" />
<ColumnDefinition Width="0.414*" />
<ColumnDefinition Width="0.586*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Bd" HorizontalAlignment="Stretch"
Grid.Column="1" Grid.ColumnSpan="1" Background="#7F058956">
<ContentPresenter x:Name="PART_Header" Margin="10,0" />
</Border>
<WrapPanel x:Name="ItemsHost"
Grid.Column="2" IsItemsHost="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My Search Hierarchical Data Template
<HierarchicalDataTemplate DataType="{x:Type local:SearchViewModel}" ItemsSource="{Binding MySearch.Custodians}" ItemContainerStyle="{StaticResource AlteredTreeViewItem}">
<TextBlock Text="{Binding MySearch.SearchName}" Foreground="Black" FontFamily="Arial" FontSize="16"/>
</HierarchicalDataTemplate>
Surely it is possible to both style differently and have child items laid out differently? How can this be achieved?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看来你已经非常接近你所追求的了。我尝试根据您发布的代码重新创建您的场景,并注意到它的一些问题(这当然是基于我对您发布的代码的解释)
ContentSource=
部分ContentPresenter
的“Header”HierarchicalDataTemplate
级别应用了ItemContainerStyle
。应该在父级上指定它,以便影响子级(在您的情况下为SearchListViewModel
)。TreeViewItem
的默认Template
以Auto
大小的ColumnDefinition
布局ContentPresenter
,因此除非您也修改父项的ItemContainerStyle
,否则WrapPanel
将不会成功换行。 我在下面的示例中将其更改为UniformGrid
通过上面的更改和其他一些内容,我得到了一个看起来像这样的结果,希望与您的结果非常接近 之后
在
,我在此处上传了示例解决方案:https://www.dropbox.com/s/4v2t8imikkagueb/TreeViewAltered.zip? dl=0
这是它的 Xaml 代码(代码太多,无法全部发布..)
It seems that you are pretty close to what you're after. I tried to recreate your scenario based on the code you posted and I noted some problems with it (which of course are based on my interpretation of the code you posted)
ContentSource="Header"
part of theContentPresenter
ItemContainerStyle
at the wrongHierarchicalDataTemplate
level. It should be specified on the parent in order to affect the children (in your caseSearchListViewModel
).Template
forTreeViewItem
lays out theContentPresenter
in anAuto
sizedColumnDefinition
so theWrapPanel
won't succesfully wrap unless you modify theItemContainerStyle
for the parent as well. I changed it to aUniformGrid
in my sample belowWith the changes from above and a few other things I got a result that looks like this which hopefully is pretty close to what you're after
I uploaded the sample solution here: https://www.dropbox.com/s/4v2t8imikkagueb/TreeViewAltered.zip?dl=0
And here is the Xaml code for it (too much code to post it all..)
很久以前,我在尝试创建类似界面时了解到,使用
ListBox
比TreeView更好 /代码>。
为什么?
如果您只有一级扩展(如示例中所示),您将对布局有更多控制,因为您有一个
DataTemplate
来设置样式。自定义
ListBox
比TreeView
容易得多,因为您不必关心GridViewColumnHeader
和GridViewColumnPresenters
等等要获得扩展部分(这就是您最初选择
TreeView
的原因),只需使用定义了两行的Grid
和一个Expander
> 在第二行绑定到ToggleButton
的IsChecked
属性。请参阅我从日志查看器中提取的示例。您能看到定义标头和可扩展主体是多么容易吗?如果您确实需要嵌套数据,请在您的视图模型中添加 Level 属性(您正在使用 MVVM,不是吗?!),然后创建一个返回 Margin 的
IValueConverter
(即厚度
)来伪造缩进。Something I learnt a long time ago when trying to create a similar interface was that you are better using a
ListBox
than aTreeView
.Why?
If you only have one level of expansion (as it appears from your sample) you will a lot more control of the layout as you have a single
DataTemplate
to style.It is lot easier to customize a
ListBox
than aTreeView
as you do not have be concerned with theGridViewColumnHeader
andGridViewColumnPresenters
etc.To get the expansion part (which is why you initially selected a
TreeView
), simply use aGrid
with two rows defined and anExpander
in the second row bound to theIsChecked
property of aToggleButton
. See the example that I pulled from my Log Viewer.Can you see how much easier it is to define a header and expandable body. If you do have a need for nested data, add a Level property your view model (you are using MVVM aren't you?!) and then create a
IValueConverter
that returns a Margin (i.e.Thickness
) to fake the indent.