Click here to Skip to main content
15,566,814 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I've got a stupid problem with clicking on a custom control (a red grid with a yellow rectangle in the center) in a canvas.

EDIT: The xaml code always gets messed up and truncated. I don't know how to post this properly...

The custom control:
XAML:
XML
<resourcedictionary>
    <controltemplate x:key="TESTCONTROL" targettype="{x:Type local:TestControl}">
        <grid background="Red">
            <rectangle width="50" height="50" verticalalignment="Center" 
                       horizontalalignment="Center" fill="Yellow">

        <Setter Property="Template" Value="{StaticResource TESTCONTROL}"/>


Code:
C#
public class TestControl : Control
{

}


There are 2 different cases I've made:

1) Directly adding the custom control to a Canvas:
XAML:
XML
<window>
  <canvas x:name="TestCanvas" mouseleftbuttondown="TestCanvas_MouseLeftButtonDown">


Code:
C#
public partial class MyWindow : Window
{
  public MainWindow()
  {
    InitializeComponent();

    TestControl control = new TestControl();
    control.Width = 100;
    control.Height = 100;

    TestCanvas.Children.Add(control);
  }
}


2) Using an ItemsControl with a Canvas as ItemPanel (ItemsSource + List)
XAML:
XML
<window>
  <itemscontrol x:name="TestItemsCtrl">
    <itemscontrol.itemspanel>
      <itemspaneltemplate>
        <canvas mouseleftbuttondown="TestCanvas_MouseLeftButtonDown">


Code:
C#
public partial class MyWindow : Window
{
  public MainWindow()
  {
    InitializeComponent();

    TestControl control = new TestControl();
    List<testcontrol> controlList = new List<testcontrol>();
    controlList.Add(control);

    TestItemsCtrl.ItemsSource = controlList;
  }
}


Now if I start the program and click on the control I check the e.Source/e.OriginalSource argument:
C#
private void TestCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  Title = e.Source.GetType().Name;
}


For case 1 this displays "TestControl" no matter where I click on my TestControl. This is my desired behaviour.
For case 2 this displays the class name of whatever part of "TestControl" I clicked on. ("Grid" or "Rectangle").

Why does this difference exist and what can I do to get the whole TestControl instead of its parts while still using an ItemsControl?

What I have tried:

I've tried an ItemTemplate with my ItemsControl altough I don't need one/shouldn't need one because the ItemsSource contains controls itself so there is no need for a template in this case.

I've tried attaching the event to the ItemsControl instead of the Canvas (ItemsPanel).
This didn't make any meaningful difference. (Except source contained e.Source contained the ItemsControl itself and e.OriginalSource contained the Grid/Rectangle parts of my TestControl instead of the TestControl itself.
Posted
Updated 25-Oct-16 3:59am
v9
Comments
#realJSOP 25-Oct-16 9:05am    
I updated my solution.

1 solution

Put one of these in your event handler:

C#
Canvas ctrl = sender as Canvas;


- or -

C#
Canvas ctrl = (Canvas)sender;


If canvas is null, call this method:

C#
/// <summary>
/// Finds the parent.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="child">The child.</param>
/// <returns></returns>
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
    //get parent item
    DependencyObject parentObject = VisualTreeHelper.GetParent(child);
 
    //we've reached the end of the tree
    if (parentObject == null) return null;
 
    //check if the parent matches the type we're looking for
    T parent = parentObject as T;
    if (parent != null)
    {
        return parent;
    }
    else
    {	 
        return FindParent<T>(parentObject);
    }
}


Usage:

C#
Canvas canvas = FindParent<canvas>(sender);


Remember, you still have to determine if sender is a canvas before calling that method, just in case the user actually clicked on the canvas, as opposed to a child control on the canvas.
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900