如何包装在TreeView控件TextBlock的内容?(How to wrap TextBlock

2019-06-25 18:38发布

我有TreeView ,显示使用数据模板的一些数据。 这里的XAML:

<TreeView Grid.Row="0" ItemsSource="{Binding Railways}" x:Name="tvDatawareObjects"
          ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.Resources>
        <!-- other templates here... -->
        <HierarchicalDataTemplate DataType="{x:Type viewModels:ProjectViewModel}" ItemsSource="{Binding Phases}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <TextBlock Text="{Binding Model.Code}" FontWeight="DemiBold" />
                <TextBlock Text="{Binding Model.Title}" TextWrapping="Wrap" Foreground="Gray" Grid.Row="1" />
            </Grid>
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type viewModels:CollectionViewModel}" ItemsSource="{Binding Items}">
            <TextBlock Text="{Binding CollectionName}" />
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

文字环绕用于<TextBlock Text="{Binding Model.Title}" TextWrapping="Wrap" Foreground="Gray" Grid.Row="1" />不起作用。 我究竟做错了什么?

Answer 1:

我相信TextBlock没有包装,因为它不具有已定义的宽度。 网格列的TextBlock是有一个*宽的,这将增加TextBlock生长在宽度。 尝试设置在一个宽度TextBlock或列,看看是否变化导致TextBlock来包装。

更新:

具体而言,该问题是TreeViewItem将自身大小到其内容的大小, ColumnDefinition将填补(无限)的可用空间和TextBlock ,没有宽度限制,将永远不会换行。 这个帖子确实描述树型视图的行为的一个好工作。 概括起来:在内容方面TreeViewItem设置为“自动”,因此将增长到适合的内容。 要明确设置的宽度TreeViewItem尝试结合您的ColumnDefinition宽度的TreeViewActualWidth

XAML:

<TreeView Width="100">
    <TreeViewItem>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType=TreeView}, Path=ActualWidth}"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <TextBlock Text="Lorem Ipsum" />
            <TextBlock Text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book." 
                       TextWrapping="Wrap" Grid.Row="1"/>
            </Grid>
        </TreeViewItem>
    </TreeView>


Answer 2:

我做的。 :)

Accordind的链接,在丹的回答中提供,原因是平躺在默认TreeViewItemTemplate。

不幸的是,简单的结合TreeView.ActualWidth不能帮助。 这是因为每个项目的宽度小于TreeView.ActualWidth定义-项目与一些水平偏移呈现,这取决于他们的水平。

因此,要解决这个问题,我需要计算这样的项目的宽度:

width = actual_width_of_tree_view - relative_horizontal_offset_of_item

更精确地说,我需要ScrollViewer.ViewportWidth ,从而TreeViewContent可能会垂直滚动,以及可视面积TreeView将小于TreeView.ActualWidth在这种情况下。

这里的附加属性:

    public static Double GetProjectTitleWidth(DependencyObject obj)
    {
        return (Double)obj.GetValue(ProjectTitleWidthProperty);
    }

    public static void SetProjectTitleWidth(DependencyObject obj, Double value)
    {
        obj.SetValue(ProjectTitleWidthProperty, value);
    }

    public static readonly DependencyProperty ProjectTitleWidthProperty = DependencyProperty.RegisterAttached(
        "ProjectTitleWidth", 
        typeof(Double), 
        typeof(DatawareSearchView),
        new UIPropertyMetadata(0.0, ProjectTitleWidthChanged));

    private static void ProjectTitleWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var targetElement = d as FrameworkElement;
        if (targetElement != null)
        {
            var bindingExpr = targetElement.GetBindingExpression(ProjectTitleWidthProperty);
            var sourceElement = bindingExpr.DataItem as FrameworkElement;
            if (sourceElement != null)
            {
                // calculating relative offset
                var leftTop = targetElement.TranslatePoint(new Point(0.0, 0.0), sourceElement);

                // trying to find ScrollViewer
                var border = VisualTreeHelper.GetChild(sourceElement, 0);
                if (border != null)
                {
                    var scrollViewer = VisualTreeHelper.GetChild(border, 0) as ScrollViewer;
                    if (scrollViewer != null)
                    {
                        // setting width of target element
                        targetElement.Width = scrollViewer.ViewportWidth - leftTop.X;
                    }
                }
            }
        }
    }

...和标记:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <TextBlock Text="{Binding Model.Code}" FontWeight="DemiBold" />
    <TextBlock Text="{Binding Model.Title}" TextWrapping="Wrap" Foreground="Gray" x:Name="tbTitle" Grid.Row="1"
               localviews:DatawareSearchView.ProjectTitleWidth="{Binding RelativeSource={RelativeSource AncestorType=TreeView}, Path=ActualWidth}"/>
</Grid>

当然,提供的解决方案是不是普遍的-它假定,即TreeView控件有BorderScrollViewer



Answer 3:

试试这个

<TextBlock Text="{Binding Model.Title}" Width="{Binding ActualWidth,
      ElementName=tvDatawareObjects}" TextWrapping="Wrap" Foreground="Gray" Grid.Row="1"/>


文章来源: How to wrap TextBlock content in TreeView?