在我的mousedown事件中获取整个自定义控件

在我的mousedown事件中获取整个自定义控件

问题描述:





我在画布上点击自定义控件(中间有一个黄色矩形的红色网格)时遇到了一个愚蠢的问题。



编辑:xaml代码总是被弄乱并被截断。我不知道如何妥善发布...



自定义控件:

XAML:

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.

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

The custom control:
XAML:

<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:

public class TestControl : Control
{

}





我做过两种不同的案例:



1)直接将自定义控件添加到画布:

XAML:



There are 2 different cases I've made:

1) Directly adding the custom control to a Canvas:
XAML:

<window>
  <canvas x:name="TestCanvas" mouseleftbuttondown="TestCanvas_MouseLeftButtonDown">





代码:



Code:

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

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

    TestCanvas.Children.Add(control);
  }
}





2)使用带有Canvas的ItemsControl作为ItemPanel(ItemsSource + List )

XAML:



2) Using an ItemsControl with a Canvas as ItemPanel (ItemsSource + List)
XAML:

<window>
  <itemscontrol x:name="TestItemsCtrl">
    <itemscontrol.itemspanel>
      <itemspaneltemplate>
        <canvas mouseleftbuttondown="TestCanvas_MouseLeftButtonDown">





代码:



Code:

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

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

    TestItemsCtrl.ItemsSource = controlList;
  }
}





现在,如果我启动程序并点击控件,我会检查e.Source /e.OriginalSource参数:



Now if I start the program and click on the control I check the e.Source/e.OriginalSource argument:

private void TestCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  Title = e.Source.GetType().Name;
}





对于案例1,无论我在哪里点击TestControl,都会显示TestControl。这是我想要的行为。

对于案例2,它显示我点击的TestControl的任何部分的类名。 (网格或矩形)。



为什么存在这种差异,如何在仍然使用ItemsControl的情况下获取整个TestControl而不是其部件?



我尝试过的事情:



我试过了ItemTemplate与我的ItemsControl尽管我不需要一个/不应该需要一个,因为ItemsSource包含控件本身所以在这种情况下不需要模板。



我尝试将事件附加到ItemsControl而不是Canvas(ItemsPanel)。

这没有任何有意义的区别。 (除了源包含e.Source包含ItemsControl本身和e.OriginalSource包含我的TestControl的Grid / Rectangle部分而不是TestControl本身。



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.

放一个这些在您的事件处理程序中:



Put one of these in your event handler:

Canvas ctrl = sender as Canvas;





- 或 -





- or -

Canvas ctrl = (Canvas)sender;





如果canvas为null,请调用此方法:





If canvas is null, call this method:

/// <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:

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.