2013-01-10 23 views
2

在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();部分,就足以从内存中删除按钮和事件,如果我离开的东西(如事件处理程序)漂浮出来那里?

与往常一样,我也乐于接受有关改进上述代码的建议。

+0

安东尼有你尝试添加/测试'WrapPanel_Main.Children。清除();'?如果是的话,它会产生什么结果..? – MethodMan

+0

'WrapPanel_Main.Children.Clear();'代码从WrapPanel中删除了按钮,但我不确定它们是否被存储在别的地方,以及它是否删除了偶数处理程序,我不知道如何测试。我不知道事件处理程序幕后会发生什么'魔术'。 –

+0

你可以做一个foreach循环来检查控件..?只是好奇.. – MethodMan

回答

3

总之,你不需要担心这一点。

当您将事件处理程序附加到按钮时,事件处理程序不会使按钮保持活动状态时,该按钮将保持活动事件处理程序引用的任何内容。事件处理程序正在引用你的窗口,所以基本上你不能从内存中清除窗口,直到按钮离开内存。由于按钮的寿命比窗口寿命长是没有意义的,所以这不会发生。

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

+0

谢谢 - 正是我在找的;除了最后一行,我遵循了所有这些......但是也许我会明白,如果我有需要做这样的事情。 –

+0

@Servy感谢您的信息,这是否也与winforms相关? – jonathana

+0

@jonathana这是描述一般事件的行为;这些都不是特定于任何框架的。 – Servy

0

由于@Servy提到它可能不需要分离这些处理程序,但如果你真的想要唯一的方法,我可以这样做是与Reflection

这是基于你的问题(在WrapPanel的按钮按钮点击事件)

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(); 
+0

谢谢 - 超出了我现在要做的事情的范围;但是有一天这可能会派上用场! –

相关问题