C# 如果删除链接到事件的控件,是否从内存中删除事件处理程序?

C# 如果删除链接到事件的控件,是否从内存中删除事件处理程序?,c#,wpf,event-handling,dynamic-usercontrols,C#,Wpf,Event Handling,Dynamic Usercontrols,在WPF中,我创建了一个控件,可以为我动态创建按钮。在某些情况下,按钮可能会更改,需要重新创建。我目前正在使用以下工具: public void GenerateButtons() { WrapPanel_Main.Children.Clear(); foreach (ActivatedItem thisItem in Controller.ItemList.Where(sl => sl.IsTypeCompatible(typeof(ActivatedItem))))

在WPF中,我创建了一个控件,可以为我动态创建按钮。在某些情况下,按钮可能会更改,需要重新创建。我目前正在使用以下工具:

public void GenerateButtons()
{
    WrapPanel_Main.Children.Clear();

    foreach (ActivatedItem thisItem in Controller.ItemList.Where(sl => sl.IsTypeCompatible(typeof(ActivatedItem))))
    {
        Button newButton = new Button() { Content = thisItem, ToolTip = thisItem.Desc, Width = 50, Height = 25 };
        newButton.Click += new System.Windows.RoutedEventHandler(this.DynamicButtonClick);
        WrapPanel_Main.Children.Add(newButton);
    }
}
我想知道
WrapPanel_Main.Children.Clear()是否部分足以从内存中删除按钮和事件,或者如果我将一些东西(如事件处理程序)留在内存中


和往常一样,我也愿意接受关于改进上述代码的建议。

简而言之,您不必担心这一点

当您将事件处理程序附加到按钮时,事件处理程序不会使按钮保持活动状态,按钮会使事件处理程序引用的内容保持活动状态。事件处理程序正在引用窗口,因此在按钮离开内存之前,基本上无法从内存中清除窗口。因为按钮的寿命比窗口的寿命长是没有意义的,所以不会发生这种情况


换句话说,您需要注意的情况是,事件处理程序中使用的项需要比拥有该事件的类具有更短的生命周期。

正如@Servy所提到的,可能不需要分离这些处理程序,但是如果您真的想分离这些处理程序,我认为唯一的方法就是使用
反射

下面是一个基于您的问题的小示例(WrapPanel中按钮的按钮单击事件)


Anthony您是否尝试过添加/测试
WrapPanel_Main.Children.Clear()?如果是这样,它会产生什么结果?
WrapPanel_Main.Children.Clear()
code从WrapPanel中删除了按钮,但我不确定它们是否存储在其他地方,它是否删除了偶数处理程序,我不知道如何进行测试。我不知道事件处理程序的幕后“魔力”是什么。你能做一个foreach循环来检查控件吗。。?只是好奇..谢谢--正是我想要的;除了最后一行,我都听了。。。但如果我需要做这样的事情,也许我会理解。@Servy谢谢你提供的信息,这是否也与winforms有关?@jonathana这是对事件行为的一般描述;所有这些都不是特定于任何框架的。谢谢——这远远超出了我现在尝试做的范围;但这也许有一天会派上用场!
public void RemoveButtonClickHandlers(UIElementCollection elements)
{
    foreach (var button in elements.OfType<Button>())
    {
        try
        {
            var handlers = typeof(UIElement).GetProperty("EventHandlersStore", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(button, null);
            if (handlers != null)
            {
                var clickEvents = (RoutedEventHandlerInfo[])handlers.GetType()
                .GetMethod("GetRoutedEventHandlers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                .Invoke(handlers, new object[] { ButtonBase.ClickEvent });
                foreach (var clickEvent in clickEvents)
                {
                    button.Click -= (RoutedEventHandler)clickEvent.Handler;
                }
            }
        }
        catch (Exception ex)
        {
            // :(
        }
    }
}
RemoveButtonClickHandlers(WrapPanel_Main.Children);
WrapPanel_Main.Children.Clear();