1

我正在尝试创建一个自定义ContextMenu, S4ContextMenu的,实现 IDisposable 来处理内存泄漏问题,如本博客中所建议的那样:

http://silverlight.codeplex.com/workitem/6206

如博客中所述,我已将此代码包含在 S4ContextMenu 的 Dispose 函数中:

MethodInfo infos = typeof(ContextMenu).GetMethods(BindingFlags.NonPublic |  
    BindingFlags.Instance).Where(a =>     
    a.Name.Equals("HandleRootVisualMouseMove")).FirstOrDefault();

Delegate handler = Delegate.CreateDelegate(typeof(MouseEventHandler), this , infos);
EventInfo info = Application.Current.RootVisual.GetType().GetEvent("MouseMove");
info.RemoveEventHandler(Application.Current.RootVisual, handler);

它编译得很好,但是当我运行它时,我得到一个 MethodAccessException: " Attempt by method 'S4.Analytics.Client.Controls.S4ContextMenu.Dispose(Boolean)' to access method 'System.Windows.Controls.ContextMenu.HandleRootVisualMouseMove(System.Object, System.Windows.Input.MouseEventArgs)' failed."

我试过让 MethodInfoS4ContextMenu代替,ContextMenu但它返回 null。

我正在开发VS 2010, targeting Silverlight 4.

我错过了什么?

如何创建此委托?

尽管我更喜欢使用这种方法来处理内存泄漏问题,但如果有人有另一种可行的方法(并且不涉及编辑实际的ContextMenuor toolkit),那将是很棒的。

4

1 回答 1

1

我在 ContextMenu 中发现了内存泄漏。它在 InitializeRootVisual 方法中与 Silverlight 4 和 5 中发生的相同,因为没有删除鼠标事件处理程序。

_rootVisual.MouseMove += new MouseEventHandler(HandleRootVisualMouseMove);

要解决此问题,您需要重新构建 Silverlight Toolkit 项目。

  1. 从https://silverlight.codeplex.com/relases下载源代码
  2. 打开项目 Control.Input.Toolkit -> ContextMenu -> ContextMenu.cs 并用以下代码替换 InitializeRootVisual 方法:

-

private void InitializeRootVisual()
{
    if (null == _rootVisual)
    {
        // Try to capture the Application's RootVisual
        _rootVisual = Application.Current.RootVisual as FrameworkElement;
        if (null != _rootVisual)
        {
            //Repaired by Jacek Gzel
            // Ideally, this would use AddHandler(MouseMoveEvent), but MouseMoveEvent doesn't exist
            //_rootVisual.MouseMove += new MouseEventHandler(HandleRootVisualMouseMove);

            var rootVisual = _rootVisual;

            // Use a weak event listener.
            var rootVisualMouseMoveListener = new WeakEventListener<ContextMenu, object, MouseEventArgs>(this);
            rootVisualMouseMoveListener.OnEventAction = (instance, source, eventArgs) => instance.HandleRootVisualMouseMove(source, eventArgs);
            rootVisualMouseMoveListener.OnDetachAction = (weakEventListener) => rootVisual.MouseMove -= weakEventListener.OnEvent;
            rootVisual.MouseMove += rootVisualMouseMoveListener.OnEvent;
        }
    }
}
  1. 替换 Silverlight 应用程序中的 Toolkit DLL 引用。
于 2015-04-08T13:07:11.040 回答