如何在WPF中为用户控件创建用户定义(新)事件?一个小例子

时间:2012-11-19 05:02:02

标签: wpf events user-controls

我有一个usercontrol,我在其中使用一个画布,在那个画布中有一个矩形 所以我想为那个我想在主窗口中使用的用户控件(画布+矩形)创建一个click事件。 问题是我想为该用户控件创建一个新的click事件。所以如何做到这一点 请在

上显示一些示例或向我展示此特定的代码

4 个答案:

答案 0 :(得分:30)

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

在您的Usercontrol中

1。添加以下声明:

public event EventHandler UserControlClicked;

2。在您的UserControl_Clicked事件 raise the event 中,如下所示:

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

在您的MainWindow

您的usercontrol现在将有一个UserControlClicked事件,您可以注册到:

<local:UserControl1 x:Name="UC" UserControlClicked="UC_OnUserControlClicked" />

答案 1 :(得分:1)

答案 2 :(得分:0)

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

public event Action<string> onUserCodeFetched;

private void btnEnterClicked(object sender, RoutedEventArgs e)
        {
            onUserCodeFetched(PersonellCode.Text);
            PersonellCode.Text = "";
        }

答案 3 :(得分:0)

这是一个老问题,但我也发现使用类似属性的自定义事件绕过该事件很有用,如 here。您可以使用通用的 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 或后面的代码初始化的,和以前一样。