如何使用Material Design In XAML Toolkit拉伸TreeViewItem并布局内部控件
解决Material Design TreeViewItem中左右对齐控件的问题
我懂你这个头疼的问题——Material Design的TreeViewItem和原生WPF的结构不一样,常规的拉伸方法根本不生效,毕竟它的模板里藏了自定义的Presenter控件,默认没给内容留满宽度的空间。下面给你两个亲测有效的解决方案:
方案1:重写ItemContainerStyle,强制内容区域拉伸
核心是修改Material Design TreeViewItem的模板,让内部的TreeViewItemPresenter占满整个可用宽度,这样你的DataTemplate布局才能生效。示例代码如下:
<TreeView ItemsSource="{Binding YourItems}" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"> <TreeView.ItemContainerStyle> <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource MaterialDesignTreeViewItem}"> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TreeViewItem}"> <Grid> <!-- 保留Material Design原有的箭头、缩进等视觉结构 --> <materialDesign:TreeViewItemPresenter x:Name="PART_TreeViewItemPresenter" Content="{TemplateBinding Header}" HorizontalAlignment="Stretch" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsExpanded="{TemplateBinding IsExpanded}" IsSelected="{TemplateBinding IsSelected}" Margin="{TemplateBinding Padding}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </TreeView.ItemContainerStyle> <TreeView.ItemTemplate> <DataTemplate x:Key="DTBooleanOption"> <!-- 用Grid实现左右对齐,中间列填充空白 --> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding OptionName}" VerticalAlignment="Center"/> <ToggleButton Grid.Column="2" Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding IsEnabled}" VerticalAlignment="Center"/> </Grid> </DataTemplate> </TreeView.ItemTemplate> </TreeView>
关键细节:一定要给TreeViewItemPresenter设置HorizontalAlignment="Stretch",这是让内容容器占满TreeView宽度的核心。
方案2:用DockPanel布局(配合宽度绑定)
如果你习惯用DockPanel,只要强制让它占满TreeViewItem的宽度,就能实现右对齐效果:
<TreeView.ItemTemplate> <DataTemplate x:Key="DTBooleanOption"> <DockPanel Width="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=ActualWidth}"> <TextBlock DockPanel.Dock="Left" Text="{Binding OptionName}" VerticalAlignment="Center"/> <ToggleButton DockPanel.Dock="Right" Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding IsEnabled}" VerticalAlignment="Center"/> </DockPanel> </DataTemplate> </TreeView.ItemTemplate>
这里通过绑定DockPanel的宽度到父级TreeViewItem的实际宽度,强制让布局容器拉满,ToggleButton自然就会靠到最右侧。
为什么原生WPF的方法没用?
Material Design的TreeViewItem用了自定义的TreeViewItemPresenter控件,它默认的HorizontalAlignment不是Stretch,而且内部布局做了封装,直接设置TreeViewItem的HorizontalContentAlignment不会传递到内容容器上,必须显式修改Presenter的属性或者模板才行。
内容的提问来源于stack exchange,提问作者buks




