views:

141

answers:

1

I have a WPF ItemsControl with a Canvas ItemPanel. Drawing from an internal source, it displays lots of automatically generated Rectangles.

As of now, it looks like this:

<Window    
// .. NameSpaces
  >
  <Window.Resources>
    <DataTemplate x:Key="binTemplate">
      <Rectangle x:Name="Rect" VerticalAlignment="Bottom"
                 Canvas.Left="10" StrokeThickness="0">
        // .. Databinding Height, Width, etc
      </Rectangle>
    </DataTemplate>
  </Window.Resources>
  <DockPanel x:Name="LayoutRoot" LastChildFill="True">
      <ItemsControl
          ItemsSource="{Binding Bins}"
          ItemTemplate="{StaticResource binTemplate}">
        <ItemsControl.ItemsPanel>
          <ItemsPanelTemplate>
            <Canvas MouseDown="Canvas_MouseDown" MouseMove="Canvas_MouseMove" MouseUp="Canvas_MouseUp">
              <Rectangle x:Name="Selection" Canvas.Left="0" Canvas.Top="0" Visibility="Hidden" />
            </Canvas>
          </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
      </ItemsControl>
  </DockPanel>
</Window>

I now try to implement a selection box, too.. well.. select my Rectangles. =) I tried just adding the box into the ItemsControl PanelTemplate, and controlling it with the Canvas mouse events, but it appears I am not allowed to do so. The error message is "Cannot explicitly modify Children collection of Panel used as ItemsPanel for ItemsControl. ItemsControl generates child elements for Panel."

What is the preferred way to implement such behavior? I thought about overlaying another canvas (using negative Margin) and drawing the selection box in there, but that seems like a bad hack.

Thanks in advance!

+2  A: 

Rather than adding the selection box to the Canvas, you should add it as an Adorner over the Canvas. To retrieve the AdornerLayer for the Canvas, you can use the AdornerLayer.GetAdornerLayer method, or wrap the Canvas in an AdornerDecorator and use its AdornerLayer property.

Thomas Levesque
Wrapping the canvas in an `AdornerDecorator` does not work, since ItemPanelTemplate only accepts Panels, but I think I can get this working in the code behind. Thanks!
Jens