2015-03-05 4 views
0

У меня есть TreeView, содержащий родителя и пару детей. Дети, в свою очередь, состоят из WrapPanel с собственными детьми («Один», «Два», «Три» и т. Д.). Как я могу заставить эти последние элементы обернуть, когда родительское окно недостаточно велико, чтобы разместить их?Как обернуть WrapPanel детей в TreeView?

Вот мой код:

<TreeView ScrollViewer.HorizontalScrollBarVisibility="Disabled"> 

    <TreeViewItem Header="Parent" IsExpanded="True" > 

     <ItemsControl> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <WrapPanel Orientation="Horizontal"/> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.Items> 
       <TextBlock Text="One" /> 
       <TextBlock Text="Two" /> 
       <TextBlock Text="Three" /> 
       <TextBlock Text="Four" /> 
       <TextBlock Text="Five" /> 
       <TextBlock Text="Six" /> 
       <TextBlock Text="Seven" /> 
       <TextBlock Text="Eight" /> 
       <TextBlock Text="Nine" /> 
       <TextBlock Text="Ten" /> 
      </ItemsControl.Items> 
     </ItemsControl> 

     <ItemsControl> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <WrapPanel Orientation="Horizontal"/> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.Items> 
       <TextBlock Text="One" /> 
       <TextBlock Text="Two" /> 
       <TextBlock Text="Three" /> 
       <TextBlock Text="Four" /> 
       <TextBlock Text="Five" /> 
       <TextBlock Text="Six" /> 
       <TextBlock Text="Seven" /> 
       <TextBlock Text="Eight" /> 
       <TextBlock Text="Nine" /> 
       <TextBlock Text="Ten" /> 
      </ItemsControl.Items> 
     </ItemsControl> 

    </TreeViewItem> 

</TreeView> 

И вот что он в настоящее время производит:

enter image description here

+0

Установив ширину в ItemsControl/WrapPanel, вы можете добиться обертывания –

ответ

1

Пожалуйста, проверьте этот обходной путь. Вы должны добавить SizeChanged="TreeView_SizeChanged" в пункт TreeView.

private void TreeView_SizeChanged(object sender, SizeChangedEventArgs e) 
{ 
    var treeView = (TreeView) sender; 
    foreach (TreeViewItem treeViewItem in treeView.Items) 
    { 
     foreach (ItemsControl ic in treeViewItem.Items) 
     { 
      Point relativeLocation = ic.TranslatePoint(new Point(0, 0), treeView); 
      var wpMaxWidth = treeView.ActualWidth - relativeLocation.X; 

      WrapPanel itemsWp = GetVisualChild<WrapPanel>(ic); 
      itemsWp.MaxWidth = wpMaxWidth; 
     } 
    } 
} 

private static T GetVisualChild<T>(DependencyObject parent) where T : Visual 
{ 
    int numVisuals = VisualTreeHelper.GetChildrenCount(parent); 
    for (int i = 0; i < numVisuals; i++) 
    { 
     Visual v = (Visual) VisualTreeHelper.GetChild(parent, i); 
     var child = v as T; 
     return child ?? GetVisualChild<T>(v); 
    } 
    return null; 
} 

Решение 2: Использование MultiBinding и IMultiValueConverter.

... 
<WrapPanel.MaxWidth> 
    <MultiBinding Converter="{StaticResource Converter1}"> 
     <MultiBinding.Bindings> 
      <Binding RelativeSource="{RelativeSource Self}"/> 
      <Binding RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=TreeView}"/> 
     </MultiBinding.Bindings> 
    </MultiBinding> 
</WrapPanel.MaxWidth> 
... 

Реализация IMultiValueConverterConvert метод:

... 
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
{ 
    var wp = values[0] as WrapPanel; 
    var tv = values[1] as TreeView; 
    if (wp == null || tv == null) 
     return 0d; 

    Point relativeLocation = wp.TranslatePoint(new Point(0, 0), tv); 
    var wpMaxWidth = tv.ActualWidth - relativeLocation.X; 
    return wpMaxWidth; 
} 
... 

ПРИМЕЧАНИЕ: Вы должны обновить Binding после изменения размера контейнера.

+0

Спасибо dbvega. Я использую MVVM, поэтому я попробовал второй метод, и он отлично работает. Мне не пришлось обновлять привязку, хотя, если я изменяю MultiBinding, чтобы также привязываться к «ActualWidth» TreeView, тогда он будет вызываться при каждом изменении размера. Мне также пришлось добавить дополнительную пару строк, чтобы учесть ширину вертикальной полосы прокрутки, если она видна. Я надеялся, что существует способ решить этот вопрос, используя регулярные свойства макета WPF, но если никто не опубликует решение, подобное ему на следующий день или около того, я помечаю это как ответ. –