How to load large number of controls in Canvas selectively

790 views Asked by At

I have a big size Canvas and a lot of small user controls placed over it. At a time only a small portion of the canvas is visible on screen. The usercontrols are created by the ItemsControl which is Data bound to a ViewModel.

<Canvas Height="10000" Width="10000" Background="White" >
    <ItemsControl ItemsSource="{Binding Path=MyData}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Views:MyControl />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="{Binding Left}"/>
                <Setter Property="Canvas.Top" Value="{Binding Top}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
</Canvas>

Now since the number of usercontrols is huge, it takes a lot of time to load the whole canvas. I want to load only those controls which are in the visible frame currently. If I move the canvas, the usercontrols under the new visible area should be loaded. The prime reason I want to do this is because of performance lag associated with loading large number of usercontrols. I want to do it in Canvas what VirtualizingStackPanel does to StackPanel.

Is there a way to do it?

Thanks for the help

2

There are 2 answers

0
Rob Smyth On

First, test loading blank user controls. That is user controls that display nothing at all. If this is fast enough it tells us that the problem is not in the canvas handling the large number of user controls but in initialising the user controls.

So, if that is the case, create a simple place holder user control that on IsVisibleChanged event firing loads the target user control using itself as the canvas.

All depends on the first test.

0
Csaba Fabian On

Look into virtualization. Instead of using Canvas, use a ListBox with your own implementation of VirtualizingPanel, that can act just as a Canvas and will only create the controls that are supposed to be visible.

There are many great resources on UI virtualization, here are two quick picks: