2012-06-26 2 views
2

У меня есть TreeView, который отображает некоторые данные с использованием шаблонов данных. Вот XAML:Как обернуть содержимое TextBlock в TreeView?

<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

я это сделал. :)

В соответствии со ссылкой, приведенной в ответе Дэна, причина лежит в стандартном 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 имеет Border и ScrollViewer.

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

Я думаю, вы вводите в заблуждение «*» и «Auto». «*» означает «заполнить все свободное пространство», «Авто» означает «получить пространство столько, сколько необходимо».В моем примере разметки «все свободное пространство» должно быть шириной TreeViewItem, которая отображает мой элемент данных. Ширина TVI, по очереди, должна быть ограничена шириной TreeView (это мое предположение), но это не происходит. – Dennis

+0

спасибо за ссылку, это хорошее объяснение источника проблемы. О привязке к фактической ширине TreeView - см. Мой ответ ниже. – Dennis