如何在 TreeView 中包装 TextBlock 内容? [英] How to wrap TextBlock content in TreeView?

查看:21
本文介绍了如何在 TreeView 中包装 TextBlock 内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 TreeView,它使用数据模板显示一些数据.这是 XAML:

I have TreeView, which displays some data using data templates. Here's 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"/> 的文本换行不起作用.我做错了什么?

Text wrapping for <TextBlock Text="{Binding Model.Title}" TextWrapping="Wrap" Foreground="Gray" Grid.Row="1" /> doesn't work. What am I doing wrong?

推荐答案

我做到了.:)

根据 Dan 的回答中提供的链接,原因在于默认的 TreeViewItemTemplate.

Accordind to the link, provided in the Dan's answer, the reason is lying in the default TreeViewItemTemplate.

不幸的是,对 TreeView.ActualWidth 的简单绑定无济于事.这是因为根据定义,每个项目的宽度小于 TreeView.ActualWidth - 项目渲染时有一些水平偏移,具体取决于它们的级别.

Unfortunately, simple binding to TreeView.ActualWidth can't help. This is because width of each item is less than TreeView.ActualWidth by definition - items are rendered with some horizontal offset, depending on their level.

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

Hence, to solve the problem, I need to calculate width of item like this:

width = actual_width_of_tree_view - relative_horizontal_offset_of_item

更准确地说,我需要ScrollViewer.ViewportWidth,因为TreeViewContent 可能会垂直滚动,并且TreeView 的可见区域将小于TreeView.实际宽度在这种情况下.

To be more precise, I need ScrollViewer.ViewportWidth, so as TreeViewContent might be scrolled vertically, and visible area of TreeView will be less than TreeView.ActualWidth in this case.

这是附加的财产:

    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.

Of course, provided solution isn't universal - it assumes, that TreeView has Border and ScrollViewer.

这篇关于如何在 TreeView 中包装 TextBlock 内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆