1
votes

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.

1
I need to show different views associated with different view models in itemsControls using observablecollections as what you did. I am new to WPF. Can you share your code with me!Manish Dubey
@Manish Dubey, see the code in the accepted answer belowGilShalit

1 Answers

6
votes

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>