3

Inside a Page I have the below TreeView. How can I get the things inside the ItemsControl to wrap instead of scrolling off the edge of the page? The WrapPanel doesn't seem to be doing anything.

Note this is not the same as asking how to wrap leaf items--I don't need to wrap ItemsControls (there's only one), but need to wrap the things inside the ItemsControl.

<TreeView
    VirtualizingPanel.IsVirtualizing="True"
    VirtualizingPanel.VirtualizationMode="Recycling"
    VirtualizingPanel.ScrollUnit="Pixel"
    VirtualizingPanel.IsVirtualizingWhenGrouping="True"
    Name="Tree">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate
            DataType="{x:Type viewModel:HighLevelItem}"
            ItemsSource="{Binding MidLevelItems}">
            <TextBlock
                Text="{Binding HighLevelName}"/>
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate
                    DataType="{x:Type viewModel:MidLevelItem}">
                    <Expander>
                        <Expander.Header>
                            <TextBlock
                                Text="{Binding MidLevelName}"/>
                        </Expander.Header>
                        <Expander.Content>
                            <ItemsControl
                                ItemsSource="{Binding LowLevelItems}">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <WrapPanel
                                            Orientation="Horizontal"/>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <TextBlock
                                            Text="{Binding LowLevelName}"/>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </Expander.Content>
                    </Expander>
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

...here are some type definitions:

public class HighLevelItem
{
    public MidLevelItem[] MidLevelItems { get; set; }
    public string HighLevelName { get; set; }
}
public class MidLevelItem
{
    public LowLevelItem[] LowLevelItems { get; set; }
    public string MidLevelName { get; set; }
}
public class LowLevelItem
{
    public string LowLevelName { get; set; }
}

...and somewhere else in your code (to get the TreeView to populate):

Tree.Items = new[] { new HighLevelItem { HighLevelName = "ALPHA", MidLevelItems = Enumerable.Repeat(0, 1000).Select(_ => new MidLevelItem { MidLevelName = Guid.NewGuid().ToString(), LowLevelItems = Enumerable.Repeat(0, 1000).Select(__ => new LowLevelItem { LowLevelName = "ff" }).ToArray() }).ToArray() } };

Also note that I'm using an Expander instead of continuing with another hierarchical data template because I need that layer to have items arranged horizontally, and changing the Orientation of the VirtualizingStackPanel at any layer within the tree to be different than the other layers breaks UI virtualization for the entire tree when that layer is expanded. Hence all the VirtualizingStackPanels in the above tree have a vertical/default orientation, and horizontal arrangement for the last layer comes from Expanders.

Here's what the above looks like. "ALPHA" is a TopLevelItem, the Guids are MidLevelItems, and each hex pair is an individual LowLevelItem (which you'll notice are not wrapping but continue past the edge):

Screenshot of the above code

Community
  • 1
  • 1
Matt Thomas
  • 5,279
  • 4
  • 27
  • 59
  • Please provide some sample data that can be used to reproduce your issue from scratch: https://stackoverflow.com/help/mcve – mm8 Mar 22 '17 at 13:28
  • @mm8 Let me know if the screenshot I just edited in helps? – Matt Thomas Mar 22 '17 at 13:29
  • It certainly doesn't. You should provide code snippets that anyone could just paste in to Visual Studio and run as is to reproduce your issue. – mm8 Mar 22 '17 at 13:30
  • @mm8 I edited in some code that is similar enough to get the point across. Let me know if that helps – Matt Thomas Mar 22 '17 at 13:49
  • You need to specify the Width of the Expander, e.g.: – mm8 Mar 22 '17 at 14:18
  • @mm8 Thank you. Due to indenting the Expander will always be offset to the right, pushing it just past the viewport, but that's easy to fix. If you put that in answer form I'll accept it – Matt Thomas Mar 22 '17 at 14:49

1 Answers1

1

You need to specify the Width of the Expander, e.g.:

<Expander Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=TreeView}}">
...

You may want to use a converter or something that subtracts the offset from the left edge side from the ActualWidth of the TreeView.

mm8
  • 163,881
  • 10
  • 57
  • 88