26

我有一个UserControl,我在其中使用一个Canvas,在那个 Canvas 中使用一个 Rectangle。我想为该用户控件(画布和矩形)创建一个单击事件,然后我想在主窗口中使用它。

问题是:我想为UserControl. 怎么做?请显示小示例或代码。

4

3 回答 3

64

关于如何从主窗口可以注册的 UserControl 公开事件的简要示例:

在您的用户控件中:

1. 添加以下声明:

public event EventHandler UserControlClicked;

2. 在您的 UserControl_Clicked 事件中引发如下事件

 private void UserControl_MouseDown(object sender, MouseButtonEventArgs e)
 {
        if (UserControlClicked != null)
        {
            UserControlClicked(this, EventArgs.Empty);
        }
  }

在您的 MainWindow 中

您的用户控件现在将有一个UserControlClicked您可以注册到的事件:

<local:UserControl1 x:Name="UC" UserControlClicked="UC_OnUserControlClicked" />
于 2012-11-19T09:10:18.807 回答
0

我发现这更容易将值传递给处理程序:

public event Action<string> onUserCodeFetched;

private void btnEnterClicked(object sender, RoutedEventArgs e)
        {
            onUserCodeFetched(PersonellCode.Text);
            PersonellCode.Text = "";
        }
于 2019-05-01T05:34:15.920 回答
0

这是一个老问题,但我也发现使用类似属性的自定义事件绕过事件很有用,就像这里一样。您可以使用通用的 EventHandler,也可以更具体(RoutedEventHandler、MouseButtonEventHandler 等)来避免以后的强制转换。例如,要绕过点击事件,您可以在自定义控件类中编写:

        public readonly object objectLock = new object();
        public event RoutedEventHandler CustomClick
        {
            add{  lock (objectLock) { myClickableInnerControl.Click += value;}}
            remove {lock (objectLock) { myClickableInnerControl.Click -= value; }}
        }

对于PreviewMouseDown 事件,它类似于:

        public readonly object objectLock = new object();
        public event MouseButtonEventHandler CustomPreviewMouseDown
        {
            add{  lock (objectLock) { myInnerControl.PreviewMouseDown += value;}}
            remove {lock (objectLock) { myInnerControl.PreviewMouseDown -= value; }}
        }

在这种情况下,myInnerControl 将是您的画布。

然后您可以将 xaml 中的事件初始化为

    <local:myClickableControl x:Name="ClickCtrl1" CustomClick="ClickCtrl1_CustomClick" />

或者

    <local:myCustomControl x:Name="CustomCtrl1" CustomPreviewMouseDown="CustomCtrl1_CustomPreviewMouseDown" />

从后面的代码:

        ClickCtrl1.CustomClick+=ClickCtrl1_CustomClick;

或者

        CustomCtrl1.CustomPreviewMouseDown+=CustomCtrl1_CustomPreviewMouseDown;

您还可以订阅多个内部控件事件的回调(当它们重叠时要小心,因为某些事件(例如 previewMouseDown 不仅由前面的控件触发,而且由下面的控件触发)。

        public readonly object objectLock = new object();
        public event MouseButtonEventHandler CustomPreviewMouseDown
        {
            add{  lock (objectLock) 
                   { 
                       myInnerControl1.PreviewMouseDown += value;
                       myInnerControl2.PreviewMouseDown += value;
                   }}
            remove {lock (objectLock) 
                    { 
                        myInnerControl1.PreviewMouseDown -= value; 
                        myInnerControl2.PreviewMouseDown -= value; 
                    }}
        }

(如果内部控件部分重叠,可以在回调方法中使用对应的 eventArgs Handled 属性来避免重复)

最后,您可以为内部控件触发的事件添加一层控件:

        bool MousePreviewDownUsed = false;
        event MouseButtonEventHandler _myPreviewMouseDownEvent = null;
        public  event MouseButtonEventHandler CustomPreviewMouseDown
        {
            add
            {
                lock (objectLock)
                {
                    _myPreviewMouseDownEvent += value;

                    if (value != null && !MousePreviewDownUsed)
                    {
                        myInnerControl.PreviewMouseDown += myInnerControl_PreviewMouseDown;
                        MousePreviewDownUsed = true;
                    }
                }
            }
            remove
            {
                lock (objectLock)
                {
                   if (_myPreviewMouseDownEvent != null)
                    {
                        _myPreviewMouseDownEvent -= value;
                        if ((_myPreviewMouseDownEvent == null || 
                             _myPreviewMouseDownEvent.GetInvocationList().Length == 0) 
                              && MousePreviewDownUsed)
                        {
                            _myPreviewMouseDownEvent = null;
                            myInnerControl.PreviewMouseDown -= myInnerControl_PreviewMouseDown;                           
                            MousePreviewDownUsed = false;
                        }
                    }
                }
            }
        }


 
        private void myInnerControl_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            // Do some previous operations or control whether the event must be broadcasted

            _myPreviewMouseDownEvent?.Invoke(sender, e);
        }

这个事件是从 xaml 或后面的代码以与以前相同的方式初始化的。

于 2021-04-07T18:05:44.527 回答