2

我有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" />不起作用。我究竟做错了什么?

4

3 回答 3

2

我相信TextBlock不是包装,因为它没有定义的宽度。所在的网格列TextBlock具有 * 宽度,该宽度将随着TextBlock宽度的增长而增长。尝试在 或 列上设置宽度TextBlock,看看更改是否会导致TextBlock换行。

更新:

更具体地说,问题在于TreeViewItemwill 将自身调整为其内容的大小,ColumnDefinition将填充(无限)可用空间TextBlock,并且 没有宽度限制,永远不会换行。这篇文章很好地描述了 TreeViewItem 的行为方式。总结一下:内容区域TreeViewItem设置为“自动”,因此它会增长以适应内容。要显式设置TreeViewItem尝试将宽度绑定ColumnDefinitionTreeView's的宽度ActualWidth

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>
于 2012-06-27T03:43:03.957 回答
1

我做到了。:)

根据 Dan 的答案中提供的链接,原因在于默认的 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.

于 2012-06-28T08:20:48.090 回答
-1

试试这个

<TextBlock Text="{Binding Model.Title}" Width="{Binding ActualWidth,
      ElementName=tvDatawareObjects}" TextWrapping="Wrap" Foreground="Gray" Grid.Row="1"/>
于 2012-06-26T15:03:09.663 回答