views:

50

answers:

2

I am in the process of taking a Silverlight 4 UserControl containing a canvas which has a number of FrameworkElements on it and converting this to use databinding.

The XAML for my original canvas was:

<Canvas x:Name="panelDisplay" >
    <Rectangle Width="50" Height="50" MouseLeftButtonDown="Element_MouseLeftButtonDown" Stroke="Aqua" StrokeThickness="5" Fill="Aquamarine" Canvas.Left="450" Canvas.Top="50" x:Name="rect1" />
    <Image Source="../Images/3.jpg" Stretch="UniformToFill" Width="356" Height="224" MouseLeftButtonDown="Element_MouseLeftButtonDown" Canvas.Left="317" Canvas.Top="140" x:Name="image1" />
</Canvas>

This displays the rectangle and image and the MouseLeftButtonDown event fires which then deals with operations such as dragging and resizing.

In order to get this working with databinding I created an object called CanvasElement:

public class CanvasElement
{
    public CanvasElement(int id, object elementContent, double width, double height, int left, int top)
    {
        Id = id;
        ElementContent = elementContent;
        Width = width;
        Height = height;
        Left = left;
        Top = top;
    }

    public int Id { get; set; }
    public object ElementContent { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
    public int Left { get; set; }
    public int Top { get; set; }
}

The ElementContent is used to store the Rectangle or Image. I populate an ObservableCollection called CanvasElements and assign the DataContext of the control. I have changed my XAML to:

<Canvas x:Name="panelDisplay" >
    <ItemsControl x:Name="CanvasElements" ItemsSource="{Binding Path=CanvasElements}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Canvas>
                    <ContentControl Content="{Binding Path=ElementContent}" Height="{Binding Path=Height}" Width="{Binding Path=Width}" 
                                Canvas.Left="{Binding Path=Left}" Canvas.Top="{Binding Path=Top}"
                                MouseLeftButtonDown="CanvasElement_MouseLeftButtonDown" />
                </Canvas>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Canvas>

My elements appear but the CanvasElement_MouseLeftButtonDown does not fire. I have also used ContentControl within the ItemsControl.

My questions are:

Is this is sensible way to go?

Why is MouseLeftButtonDown not firing?

A: 

You are better off to put the MouseLeftButtonDown event handler on the ItemsControl. Any events that happen on it's children will bubble up to it and you can handle them there.

Stephan
If I put a handler on the ItemsControl it still does not fire. If I put the handler on the parent Canvas (not the one in the DataTemplate) this does fire.
Gary Joynes
Does catching it on the Canvas solve your issue?
Stephan
A: 

I eventually decided that using the ItemsControl to bind to a collection of shapes was not the best way forward.

The main reason for this is that by using a control in the DataTemplate to house shapes adds extra complexity, in my case I have a main canvas and each shape was housed in its own canvas placed on the main canvas.

I believe this was causing the problem with the events and makes it more complex to position shapes.

Gary Joynes