Home > Back-end >  Canvas with static content and items
Canvas with static content and items

Time:05-23

I have a Canvas which contains static elements - those elements use binding to draw it in the right places. Now I need to draw other elements depending on items in a collection. I want to use ItemsControl, but I don't know how to do it correctly. My current pseudo-code:

<UserControl.Resources>
    <RectangleGeometry x:Key="MyGeometry1">
        <RectangleGeometry.Rect>
            <MultiBinding Converter="{StaticResource RectConverter}">
                <Binding Path="ActualWidth" ElementName="m_Canvas" />
                <Binding Path="ActualHeight" ElementName="m_Canvas" />
            </MultiBinding>
        </RectangleGeometry.Rect>
    </RectangleGeometry>
</UserControl.Resources>

<Canvas x:Name="m_Canvas">
    <!-- "static" content -->
    <Line x:Name="Line1" X1="{Binding Line1X1}" X2="{Binding Line1X2}" Y1="{Binding Line1Y1}" Y2="{Binding Line1Y2}"/>
    <Line X1="0" X2="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Canvas}}}" Y1="0" Y2="0">
    <Path Fill="#35A500"
          Opacity="0.15">
        <Path.Data>
            <GeometryGroup FillRule="EvenOdd">
                <StaticResource ResourceKey="MyGeometry1" />
            </GeometryGroup>
        </Path.Data>
    </Path>
    
    <Line X1="{Binding Items[0].X1}" X2="{Binding Items[0].X2}" Y1="{Binding Items[0].Y1}" Y2="{Binding Items[0].Y2}"/>
    <Line X1="{Binding Items[1].X1}" X2="{Binding Items[1].X2}" Y1="{Binding Items[1].Y1}" Y2="{Binding Items[1].Y2}"/>
    <Line X1="{Binding Items[2].X1}" X2="{Binding Items[2].X2}" Y1="{Binding Items[2].Y1}" Y2="{Binding Items[2].Y2}"/>
</Canvas>

I tried something like this:

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas>
                <!-- "static" content -->
                <Line x:Name="Line1" X1="{Binding Line1X1}" X2="{Binding Line1X2}" Y1="{Binding Line1Y1}" Y2="{Binding Line1Y2}"/>
                <Line X1="0" X2="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Canvas}}}" Y1="0" Y2="0">
            </Canvas>
        </ItemsPanelTemplate>
<!-- (...) other code -->
</ItemsControl>

But I have an error:

Error XDG0062 Cannot explicitly modify Children collection of Panel used as ItemsPanel for ItemsControl. ItemsControl generates child elements for Panel.

I understand that is because I put Line1 inside Canvas but how to make such Canvas with some kind static content and also as a container for items?

CodePudding user response:

The "static content" could be put into another Canvas above or below the ItemsPresenter in the ControlTemplate of the ItemsControl:

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <Grid>
                <Canvas>
                    <!-- "static" content -->
                </Canvas>
                <ItemsPresenter/>
            </Grid>
        </ControlTemplate>
    </ItemsControl.Template>

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

</ItemsControl>
  • Related