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();私のコードのセクションがメモリからボタンとイベントを削除するのに十分なのか、それとも (イベント ハンドラーのような) ものをそのままにしておくのか疑問に思っています。

いつものように、上記のコードを改善するための提案も受け付けています。

4

2 に答える 2

3

要するに、これについて心配する必要はありません。

ボタンにイベント ハンドラーをアタッチすると、イベント ハンドラーがボタンを有効にしない場合、ボタンはイベント ハンドラーによって参照されるものをすべて有効に保ちます。イベント ハンドラーはウィンドウを参照しているため、基本的に、ボタンがメモリを離れるまでウィンドウをメモリからクリアすることはできません。ボタンがウィンドウよりも長く存続することは実際には意味がないため、これは発生しません。

つまり、注意が必要な状況は、イベント ハンドラーで使用されるアイテムが、イベントを所有するクラスよりも短い寿命を持つ必要がある場合です。

于 2013-01-10T21:05:40.463 に答える
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();
于 2013-01-10T21:17:02.027 に答える