简体   繁体   English

如何使用反射从自定义控件中删除单击事件?

[英]How do I remove a click event from a custom control using reflection?

I have a custom control (MenuButton) in WPF that subscribes to a Click event.我在订阅 Click 事件的 WPF 中有一个自定义控件(MenuButton)。 I now want to use reflection to unsubscribe from the event.我现在想使用反射来取消订阅该事件。 This is what my code currently looks like:这是我的代码目前的样子:

private void RemoveClickEvent(MenuButton mbButton)
{
    FieldInfo fiFieldInfo = mbButton.GetType().GetField("Click", BindingFlags.Public | BindingFlags.NonPublic |
                                                        BindingFlags.Instance |BindingFlags.Static | BindingFlags.GetField);
    object objValue = fiFieldInfo.GetValue(mbButton);
    PropertyInfo piProprtyInfo = mbButton.GetType().GetProperty("Events", BindingFlags.Public | BindingFlags.NonPublic |
                                                                BindingFlags.Instance | BindingFlags.Static | BindingFlags.GetField | BindingFlags.GetProperty);

    EventHandlerList ehEventHandlers = (EventHandlerList)piProprtyInfo.GetValue(mbButton, null);
    ehEventHandlers.RemoveHandler(objValue, ehEventHandlers[objValue]);
}

I can successfully get the FieldInfo object, but the PropertyInfo object comes out as null.我可以成功获取 FieldInfo object,但 PropertyInfo object 出现为 null。 How do I fix my code so that the method works properly?如何修复我的代码以使该方法正常工作? For the record, I am targeting .NET Framework 4.作为记录,我的目标是 .NET 框架 4。

Edit:编辑:

Here is how I subscribe to the events.这是我订阅事件的方式。

private void PageStart()
{
    //Subscribe to the necessary event when a page is first loaded
    foreach (MenuButton mbItem in mbMenuButtonsList)
    {
        if (mbItem.HideExtraInfo == true)
        {
            mbButton.Click += (sender, e) => ShowOrHideControls(sender, e, true);
        }
        else
        {
            mbButton.Click += (sender, e) => ShowOrHideControls(sender, e, false);
        }
    }
}

private void PageEnd()
{
    //When moving to the next page, unsubscribe from the events
    foreach (MenuButton mbItem in mbMenuButtonsList)
    {
        RemoveClickEvent(mbItem);
    }
}

Edit #2:编辑#2:

Something I neglected to mention, some of the events I use in my project also require the MenuButton to be passed in, like so:我忽略了一点,我在项目中使用的一些事件也需要传入 MenuButton,如下所示:

UIElementCollection ctrlControls = MainCanvas.Children;
mbButton.Click += (sender, e) => ChangeControls(sender, e, mbButton, ctrlControls, false);

How do I work around this if I stop using Lambda expressions?如果我停止使用 Lambda 表达式,我该如何解决这个问题?

If instead of using lambdas to subscribe to your events, you use methods, unsubscribing is easy:如果不使用 lambdas 订阅您的事件,而是使用方法,则取消订阅很容易:

if (mbItem.HideExtraInfo == true)
{
    mbButton.Click += ShowControls;
}
else
{
    mbButton.Click += HideControls;
}

private void ShowControls(object sender, EventArgs e) => ShowOrHideControls(sender, e, true);
private void HideControls(object sender, EventArgs e) => ShowOrHideControls(sender, e, false);

private void PageEnd()
{
    //When moving to the next page, unsubscribe from the events
    foreach (MenuButton mbItem in mbMenuButtonsList)
    {
        mbItem.Click -= ShowControls;
        mbItem.Click -= HideControls;
    }
}

That's pretty easy to handle, don't use lambda expressions!这很容易处理,不要使用 lambda 表达式!

private void PageStart()
{
    //Subscribe to the necessary event when a page is first loaded
    foreach (MenuButton mbItem in mbMenuButtonsList)
    {
        if (mbItem.HideExtraInfo == true)
        {
            mbButton.Click += true_handler;
        }
        else
        {
            mbButton.Click += false_handler;
        }
    }
}

void true_handler(object sender, EventArgs args)
{
    ShowOrHideControls(sender, e, true);
}

void false_handler(object sender, EventArgs args)
{
    ShowOrHideControls(sender, e, false);
}

private void PageEnd()
{
    //When moving to the next page, unsubscribe from the events
    foreach (MenuButton mbItem in mbMenuButtonsList)
    {
        if (mbItem.HideExtraInfo == true)
        {
            mbButton.Click -= true_handler;
        }
        else
        {
            mbButton.Click -= false_handler;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM