wpfitemscontroltemplatingwpf-positioning

How can I position ViewModels in an ItemsControl


My mainwindow ViewModel has an ObservableCollection of ViewModels, called ViewModels.

The Mainwindow XAML has an ItemsControl with ItemsSource bound to ViewModels.

When I have

<ItemsControl ItemsSource="{Binding ViewModels}" />

The Views associated with each ViewModel in the collection are rendered one below the other. The Views are UserControls, displaying dataGrids.

How can I position them in a customizable way, for example such that VM1 is on the left, and VM2 and VM3 are stacked one on top of the other to the right of VM1.

Each VieModel has PosX, PosY, Width and Height properties, and I've been trying various templating methods but no success so far.

I have found examples of how to this with Observable collections of images, but one thing I'm struggling is that my collection is of ViewModels.


Solution

  • Make your ItemsControl.ItemsPanel into a Canvas, and set your Top/Left/Height/Width in the ItemTemplate.

    <ItemsControl ItemsSource="{Binding ViewModels}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <!-- Height, Width, and Background are required to render size correctly -->
                <Canvas Height="600" Width="800" Background="White" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="{x:Type FrameworkElement}">
                <Setter Property="Canvas.Top" Value="{Binding Top}" />
                <Setter Property="Canvas.Left" Value="{Binding Left}" />
                <Setter Property="Height" Value="{Binding Height}" />
                <Setter Property="Width" Value="{Binding Width}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
    
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <ContentControl>
                    <ContentPresenter ClipToBounds="True" Content="{TemplateBinding Content}"/>
                </ContentControl>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>