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."が発生します。

S4ContextMenu代わりにMethodInfo を取得しようとしましContextMenuたが、null が返されます。

で開発していVS 2010, targeting Silverlight 4ます。

私は何が欠けていますか?

このデリゲートを作成するにはどうすればよいですか?

メモリリークの問題に対処するためにこのアプローチを使用したいと思いますが、誰かが別の方法で機能する (実際のContextMenuまたはを編集する必要がない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 に答える