【问题标题】:How to stretch TreeViewItem width to fill parent?如何拉伸 TreeViewItem 宽度以填充父项?
【发布时间】:2018-04-25 19:37:58
【问题描述】:

我有一个 WPF TreeView,我想像它的父级一样将 TreeViewItem 拉伸到整个空间。

<TreeView Name="treeFamilies" AllowDrop="True" >
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:MyNode}" ItemsSource="{Binding Members}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}" Background="LightGray"/>
                <TextBlock Text=" [" Foreground="Blue" Background="LightGray"/>
                <TextBlock Text="{Binding Members.Count}" Foreground="Blue" Background="LightGray"/>
                <TextBlock Text="]" Foreground="Blue" Background="LightGray" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

看来我错误地使用了 ItemContainer 样式 &lt;Setter Property="HorizontalContentAlignment" Value="Stretch"/&gt;。我现在的树看起来像这张照片:

我希望拉伸灰色背景以填充树视图控件的整个末端。 我怎样才能做到这一点?

【问题讨论】:

  • 看看here
  • 不确定,但我认为使用 StackPanel 会给您带来一些问题。我经常无法按照我想要的方式使用它。您还可以考虑将树项的宽度、RelativeSource 绑定到父元素。
  • @Il Vic 您的链接非常有用。

标签: wpf treeview


【解决方案1】:

Form Il Vic 的评论,this msdn blog 显示了一种 hack-like 方法来删​​除 TreeViewItem 的最后一列。

如果博客关闭,我会在此处复制我的工作代码。加载TreeViewItem 后,我从网格中删除第三个ColumnDefinition,并将第二个ColumnDefinition 宽度设置为*

public class StretchingTreeViewItem : TreeViewItem
{
    public StretchingTreeViewItem()
    {
        this.Loaded += new RoutedEventHandler(StretchingTreeViewItem_Loaded);
    }

    private void StretchingTreeViewItem_Loaded(object sender, RoutedEventArgs e)
    {
        if (this.VisualChildrenCount > 0)
        {
            Grid grid = this.GetVisualChild(0) as Grid;
            if (grid != null && grid.ColumnDefinitions.Count == 3)
            {
                grid.ColumnDefinitions.RemoveAt(2);
                grid.ColumnDefinitions[1].Width = new GridLength(1, GridUnitType.Star);
            }
        }
    }

    protected override DependencyObject GetContainerForItemOverride()
    {
        return new StretchingTreeViewItem();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is StretchingTreeViewItem;
    }
}

然后我覆盖TreeView 以获取自定义项。

public class StretchingTreeView : TreeView
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new StretchingTreeViewItem();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is StretchingTreeViewItem;
    }        
}

【讨论】:

    【解决方案2】:

    您必须覆盖树视图 itemcontainerstyle 的模板,这对微软来说有点奇怪,但您必须将整个模板写成新的。所以不会有扩展器或类似的东西,但是使用此代码,您的树视图项目将延伸到整个父级。我将 IsExpanded 设置为 true,因此您的孩子仍会显示。

    <TreeView Margin="10"
                  ItemsSource="{Binding ChainedCommandVMs}">
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsExpanded"
                            Value="True" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="TreeViewItem">
                                <StackPanel>
                                    <ContentPresenter ContentSource="Header" />
                                    <ItemsPresenter Name="ItemsHost" />
                                </StackPanel>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </TreeView.ItemContainerStyle>...
    

    如果您想保持正常行为,例如查看本教程的展开按钮,它将帮助您重写整个模板: https://wpf.2000things.com/2017/09/23/1218-stretching-items-in-treeview-across-entire-control/

    【讨论】:

      【解决方案3】:

      我想出了一个非常简单的方法来实现这个(虽然也不完美):绑定到树视图的ActualWidth 属性

      <TreeView x:Name="ListUI">
        <TreeView.Resources>
          <DataTemplate>
            <Grid HorizontalAlignment="Stretch"
              Width="{Binding ActualWidth,
                ElementName=ListUI,
                Converter={StaticResource MinusFortyFiveConverter}}">
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
              </Grid.ColumnDefinitions>
              <TextBlock Grid.Column="0" Text="Left Side" />
              <!-- Will gap in the middle -->
              <TextBlock Grid.Column="2" Text="Right Side" />
            </Grid>
          </DataTemplate>
        </TreeView.Resources>
      </TreeView>
      

      您可能需要一个值转换器,将数字减少 10 左右,否则会太宽,请根据您的皮肤需要进行调整。我对默认皮肤的初始测试是负 45 是一个很好的起点。

      public class MinusFortyFiveConverter : IValueConverter
      {
          /// <inheritdoc/>
          public object Convert(
              object value, Type targetType, object parameter, CultureInfo culture)
          {
              return (double)value - 45;
          }
      
          /// <inheritdoc/>
          public object ConvertBack(
              object value, Type targetType, object parameter, CultureInfo culture)
          {
              throw new NotSupportedException("Cannot convert back");
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-08-15
        • 1970-01-01
        • 1970-01-01
        • 2011-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-27
        • 1970-01-01
        相关资源
        最近更新 更多