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

如何在WPF中为用户控件创建用户定义(新)事件?一个小示例,wpf,events,user-controls,Wpf,Events,User Controls,我有一个UserControl,在其中我使用了一个Canvas,在该Canvas中有一个矩形。我想为该用户控件(画布和矩形)创建一个单击事件,然后在主窗口中使用该事件 问题是:我想为UserControl创建一个新的单击事件。怎么做?请给出一些示例或代码。关于如何从主窗口可以注册的UserControl中公开事件的简短示例: 在用户控件中: 一,。添加以下声明: public event EventHandler UserControlClicked; 二,。在用户控件中,单击事件,如下所示:

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


问题是:我想为
UserControl
创建一个新的单击事件。怎么做?请给出一些示例或代码。

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

在用户控件中:

一,。添加以下声明:

public event EventHandler UserControlClicked;
二,。在用户控件中,单击事件,如下所示:

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

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

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

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

public event Action<string> onUserCodeFetched;

private void btnEnterClicked(object sender, RoutedEventArgs e)
        {
            onUserCodeFetched(PersonellCode.Text);
            PersonellCode.Text = "";
        }
公共事件操作onUserCodeFetched;
私有void bEnterClick(对象发送方,路由目标)
{
onUserCodeFetched(PersonellCode.Text);
PersonellCode.Text=“”;
}

这是一个老问题,但我发现使用中的自定义事件之类的属性绕过事件也很有用。您可以使用常规事件处理程序,也可以使用更具体的事件处理程序(RoutedEventHandler、MouseButtonEventHandler等),以避免以后的强制转换。例如,要绕过单击事件,可以在自定义控件类中编写:

public readonly object objectLock=new object();
公共事件路由EventHandler自定义单击
{
添加{lock(objectLock){myClickableInnerControl.Click+=value;}}
删除{lock(objectLock){myClickableInnerControl.Click-=value;}}
}
对于PreviewMouseDown事件,它将类似于:

public readonly object objectLock=new object();
公共事件鼠标按钮Venthandler CustomPreviewMouseDown
{
添加{lock(objectLock){myInnerControl.PreviewMouseDown+=value;}}
移除{lock(objectLock){myInnerControl.PreviewMouseDown-=value;}}
}
在这种情况下,myInnerControl将是您的画布

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



从代码背后:

点击Ctrl1.CustomClick+=点击Ctrl1\u CustomClick;

CustomCtrl1.CustomPreviewMouseDown+=CustomCtrl1\u CustomPreviewMouseDown;
您还可以订阅几个内部控件事件的回调(当它们重叠时要小心,因为previewMouseDown等事件不仅由前面的控件触发,而且也由下面的控件触发)

public readonly object objectLock=new object();
公共事件鼠标按钮Venthandler CustomPreviewMouseDown
{
添加{lock(objectLock)
{ 
myInnerControl1.PreviewMouseDown+=值;
myInnerControl2.PreviewMouseDown+=值;
}}
移除{lock(objectLock)
{ 
myInnerControl1.PreviewMouseDown-=值;
myInnerControl2.PreviewMouseDown-=值;
}}
}
(如果内部控件部分重叠,可以在回调方法中使用相应的eventArgs Handled属性以避免重复)

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

bool MousePreviewDownUsed=false;
事件鼠标按钮Venthandler _myPreviewMouseDownEvent=null;
公共事件鼠标按钮Venthandler CustomPreviewMouseDown
{
添加
{
锁(对象锁)
{
_myPreviewMouseDownEvent+=值;
if(值!=null&!MousePreviewDownUsed)
{
myInnerControl.PreviewMouseDown+=myInnerControl\u PreviewMouseDown;
MousePreviewDownUsed=true;
}
}
}
去除
{
锁(对象锁)
{
如果(_myPreviewMouseDownEvent!=null)
{
_myPreviewMouseDownEvent-=值;
如果(_myPreviewMouseDownEvent==null ||
_myPreviewMouseDownEvent.GetInvocationList().Length==0)
&&鼠标预览(已使用)
{
_myPreviewMouseDownEvent=null;
myInnerControl.PreviewMouseDown-=myInnerControl\u PreviewMouseDown;
MousePreviewDownUsed=false;
}
}
}
}
}
私有void myInnerControl_PreviewMouseDown(对象发送器,鼠标按钮Ventargs e)
{
//执行一些以前的操作或控制是否必须广播事件
_myPreviewMouseDownEvent?.Invoke(发送方,e);
}

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

这个问题不是很清楚。也许你可以重新措辞以澄清你的问题?你需要取消注册吗?为了完整起见,
UserControl\u MouseDown
事件还需要与XAML中实际的
MouseDown
事件绑定,显然这样做是可行的。我无法让它起作用。它告诉我UserControlClicked不可访问或无法识别。@zar另一种可能是重写当前的OnMouseDown处理程序
protected override void OnMouseDown(MouseButtonEvent