WPF ListBox TreeViewItem填充TreeView的宽度

时间:2014-05-07 04:08:49

标签: c# wpf listbox treeview listboxitem

如果我有一个使用ListBox控件作为TreeViewItems的TreeView,我如何让ListBoxItems跨越整个TreeView容器。

 <Grid>
    <TreeView>
        <TreeViewItem Header="General 1">
            <ListBox BorderThickness="0">
                <ListBoxItem>Item A</ListBoxItem>
                <ListBoxItem>Item B</ListBoxItem>
                <ListBoxItem>Item C</ListBoxItem>
            </ListBox>
        </TreeViewItem>
        <TreeViewItem Header="General 2">
            <ListBox BorderThickness="0">
                <ListBoxItem>Item A</ListBoxItem>
                <ListBoxItem>Item B</ListBoxItem>
                <ListBoxItem>Item C</ListBoxItem>
            </ListBox>
        </TreeViewItem>
        <TreeViewItem Header="General 3">
            <ListBox BorderThickness="0">
                <ListBoxItem>Item A</ListBoxItem>
                <ListBoxItem>Item B</ListBoxItem>
                <ListBoxItem>Item C</ListBoxItem>
            </ListBox>
        </TreeViewItem>
        <TreeViewItem Header="General 4">
            <ListBox BorderThickness="0">
                <ListBoxItem>Item A</ListBoxItem>
                <ListBoxItem>Item B</ListBoxItem>
                <ListBoxItem>Item C</ListBoxItem>
            </ListBox>
        </TreeViewItem>
    </TreeView>
</Grid>

这会产生如下图像的结果。请注意,所选的ListBoxItem不会跨越Treeview控件的宽度。

enter image description here

2 个答案:

答案 0 :(得分:1)

默认情况下,TreeViewItems的行为方式与您现在的行为方式相同,因此ListBox与此无关。 TreeViewItem只围绕ListBox ContentPresenter Template。为了使其跨越所选项目,高亮笔刷将需要额外的工作。

您有多个选项,可以修改TreeViewItem

<ControlTemplate TargetType="{x:Type TreeViewItem}"> <StackPanel> <Border Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="19" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <ToggleButton x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/> <ContentPresenter x:Name="PART_Header" Grid.Column="1" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/> </Grid> </Border> <ItemsPresenter x:Name="ItemsHost" Margin="19,0,0,0" /> </StackPanel> <!-- Triggers --> </ControlTemplate>
ToggleButton

问题在于它不会与ExpandCollapseToggleStyle相媲美。它只会跨越第二列项目。可以通过转到实际控制模板来提取<SolidColorBrush x:Key="GlyphBrush" Color="#444" /> <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton"> <Setter Property="Focusable" Value="False"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ToggleButton"> <Grid Width="15" Height="13" Background="Transparent"> <Path x:Name="ExpandPath" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="1,1,1,1" Fill="{StaticResource GlyphBrush}" Data="M 4 0 L 8 4 L 4 8 Z"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter Property="Data" TargetName="ExpandPath" Value="M 0 4 L 8 4 L 4 8 Z"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="TreeViewItemFocusVisual"> <Setter Property="Control.Template"> <Setter.Value> <ControlTemplate> <Border> <Rectangle Margin="0,0,0,0" StrokeThickness="5" Stroke="Black" StrokeDashArray="1 2" Opacity="0"/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="{x:Type TreeViewItem}" TargetType="{x:Type TreeViewItem}"> <Setter Property="Background" Value="Transparent"/> <Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> <Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> <Setter Property="Padding" Value="1,0,0,0"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> <Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TreeViewItem}"> <ControlTemplate.Resources> <local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" /> </ControlTemplate.Resources> <StackPanel> <Border Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"> <Grid Margin="{Binding Converter={StaticResource lengthConverter}, RelativeSource={RelativeSource TemplatedParent}}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="19" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <ToggleButton x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/> <ContentPresenter x:Name="PART_Header" Grid.Column="1" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/> </Grid> </Border> <ItemsPresenter x:Name="ItemsHost" /> </StackPanel> <ControlTemplate.Triggers> <Trigger Property="IsExpanded" Value="false"> <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/> </Trigger> <Trigger Property="HasItems" Value="false"> <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="HasHeader" Value="false"/> <Condition Property="Width" Value="Auto"/> </MultiTrigger.Conditions> <Setter TargetName="PART_Header" Property="MinWidth" Value="75"/> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="HasHeader" Value="false"/> <Condition Property="Height" Value="Auto"/> </MultiTrigger.Conditions> <Setter TargetName="PART_Header" Property="MinHeight" Value="19"/> </MultiTrigger> <Trigger Property="IsSelected" Value="true"> <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="true"/> <Condition Property="IsSelectionActive" Value="false"/> </MultiTrigger.Conditions> <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> </MultiTrigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>

即使使用切换按钮,它的另一个解决方案是使用长度转换器和TreeViewItem扩展方法来获取深度。这两者都与TreeViewItem可视树紧密耦合,所以如果你开始搞乱模板,那么你可能会遇到麻烦。

定义样式

完整TreeViewItem样式

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="19" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <ToggleButton x:Name="Expander"
                    Style="{StaticResource ExpandCollapseToggleStyle}"
                    IsChecked="{Binding Path=IsExpanded,
                    RelativeSource={RelativeSource TemplatedParent}}"
                    ClickMode="Press"/>

                <ContentPresenter x:Name="PART_Header"
                    Grid.Column="1"
                    ContentSource="Header"
                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
            </Grid>
      </Border>
      <ItemsPresenter x:Name="ItemsHost" />
    </StackPanel>
    <!-- Triggers -->
</ControlTemplate>

                                                             

public static class TreeViewItemExtensions
{
    public static int GetDepth(this TreeViewItem item)
    {
        TreeViewItem parent;
        while ((parent = GetParent(item)) != null)
        {
            return GetDepth(parent) + 1;
        }
        return 0;
    }

    private static TreeViewItem GetParent(TreeViewItem item)
    {
        var parent = VisualTreeHelper.GetParent(item);
        while (!(parent is TreeViewItem || parent is TreeView))
        {
            parent = VisualTreeHelper.GetParent(parent);
        }
        return parent as TreeViewItem;
    }
}

TreeViewDepth Extension

public class LeftMarginMultiplierConverter : IValueConverter
{
    public double Length { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var item = value as TreeViewItem;
        if (item == null)
            return new Thickness(0);

        return new Thickness(Length * item.GetDepth(), 0, 0, 0);
    }

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

<强> LeftMarginMultiplierConverter

<TreeView Margin="50">

    <TreeViewItem Header="General 1">
        <ListBox BorderThickness="0">
            <ListBoxItem>Item A</ListBoxItem>
            <ListBoxItem>Item B</ListBoxItem>
            <ListBoxItem>Item C</ListBoxItem>
        </ListBox>
    </TreeViewItem>
    <TreeViewItem Header="General 2">
        <ListBox BorderThickness="0">
            <ListBoxItem>Item A</ListBoxItem>
            <ListBoxItem>Item B</ListBoxItem>
            <ListBoxItem>Item C</ListBoxItem>
        </ListBox>
    </TreeViewItem>
    <TreeViewItem Header="General 3">
        <ListBox BorderThickness="0">
            <ListBoxItem>Item A</ListBoxItem>
            <ListBoxItem>Item B</ListBoxItem>
            <ListBoxItem>Item C</ListBoxItem>
        </ListBox>
    </TreeViewItem>
    <TreeViewItem Header="General 4">
        <ListBox BorderThickness="0">
            <ListBoxItem>Item A</ListBoxItem>
            <ListBoxItem>Item B</ListBoxItem>
            <ListBoxItem>Item C</ListBoxItem>
        </ListBox>
    </TreeViewItem>
</TreeView>

<强>控制

{{1}}

答案 1 :(得分:1)

尝试将此style应用于TreeView,

  <Style TargetType="TreeViewItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TreeViewItem">
                    <StackPanel>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="ExpansionStates">
                                <VisualState x:Name="Expanded">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames
                                    Storyboard.TargetProperty="(UIElement.Visibility)"
                                    Storyboard.TargetName="ItemsHost">
                                            <DiscreteObjectKeyFrame KeyTime="0"
                                        Value="{x:Static Visibility.Visible}" />
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Collapsed" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ContentPresenter ContentSource="Header" />
                        <ItemsPresenter Name="ItemsHost" Visibility="Collapsed" />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>