2012-06-26 67 views
2

我有TreeView,它使用数据模板显示一些数据。这里是XAML:如何在TreeView中包装TextBlock内容?

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

回答

0

我做到了。 :)

根据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

0

试试这个

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

不幸的是,它不起作用。看起来这个绑定被忽略了。同时,恒定宽度值正常工作。 :( – Dennis

2

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

更新:

具体而言,该问题是TreeViewItem意志大小本身对其内容的大小,ColumnDefinition将填补(无限)的可用空间和TextBlock,没有宽度限制,永远不会换行。 This post在描述TreeViewItem的行为方式方面做得很好。综上所述: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> 
+0

我认为,你很容易混淆“*”和“自动” “*”的意思是“填满所有可用空间”,“自动”的意思是“尽可能多地获得空间”。在我的标记示例中,“所有可用空间”必须是呈现我的数据项的TreeViewItem的宽度。 TVI的宽度必须由TreeView的宽度限制(这是我的假设),但这不会发生。 – Dennis

+0

感谢您的链接,这是问题来源的很好的解释。关于绑定到TreeView的实际宽度 - 请参阅下面的答案。 – Dennis