2

AvalonDockを含むprism/wpf/mefソリューションがあります。RegionAdapterBase<Pane>AvalonDockからのペインの作成と削除を処理するクラスを作成しました。

これが私が遭遇している問題です:

  1. メニューのボタンをクリックすると、ビューがリージョンに登録され、DocumentPane
  2. AvalonDockの閉じるボタンをクリックしてタブを閉じ、ビューを削除します
  3. 同じメニューボタンをクリックして、もう一度追加します
  4. エラーが発生しました:

「指定された要素はすでに別の要素の論理的な子です。最初に切断してください。」

だから...これは私が削除する必要がある何かが残っていることを私に教えてくれますが、それがどこにあるのかわかりません。これが私のRegionAdapterからのコードです:

private void OnViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, Pane regionTarget)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        foreach (object item in e.NewItems)
        {
            UIElement view = item as UIElement;

            if (view is ITabViewInfo)
            {
                if (view != null)
                {
                    DockableContent newContentPane = new DockableContent()
                    {
                        Content = item,
                        Title = ((ITabViewInfo)view).TabViewTitle,
                        Icon = new Image()
                        {
                            Source = new BitmapImage(((ITabViewInfo)view).TabViewIcon)
                        }.Source,
                        IsCloseable = ((ITabViewInfo)view).IsCloseable,
                        HideOnClose = ((ITabViewInfo)view).IsHideOnClose
                    };

                    newContentPane.Closed += (contentPaneSender, args) =>
                    {
                        Debug.WriteLine("Removing view from region", "Prism");
                        region.Remove(item);
                    };

                    regionTarget.Items.Add(newContentPane);
                    newContentPane.Activate();
                }
            }
        }
    } else if (e.Action == NotifyCollectionChangedAction.Remove) {
            regionTarget.Items.Clear();
    }
   }

デバッグ行から、DocumentPaneおよびリージョンビューが適切に破棄されています...クリックしてアイテムをビューに追加し直すと、次のような行に上記のエラーメッセージが表示されます。

Content = item,

メニューボタンが押されたときに実行されるモジュールのコードは次のとおりです。

    if (_regionManager.Regions["MainRegion"].Views.Any(m => m.GetType() == typeof(Views.ClassicFrontierView)))
    {
        Debug.WriteLine(_regionManager.Regions["MainRegion"].Views.Count());
    }
    else
    {
        Debug.WriteLine("Adding view to region", "Prism");
        _regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.ClassicFrontierView));
    }

私が欠けているものはありますか?

4

3 に答える 3

2

Closedイベント(基になるビューへの参照を失った可能性があります)を処理する代わりに、Closingイベントを処理します。

これは機能しましたが、タブを再度開こうとすると、同じインスタンスが表示されていました。これをCompositeWPF(Prism)で読んだ後、IRegion.AddとIRegionManager.RegisterViewWithRegionの違いは何ですか? 私はこれを変更しました:

_regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.ClassicFrontierView));

これに:

_regionManager.Regions["MainRegion"].Add(new Classic.Views.ClassicFrontierView());

メモリリークが発生しないことを確認するために、Prism / avalondockを使用して調査を行う必要がありますが、現時点では機能しているようです。

于 2011-02-14T15:57:01.470 に答える
2

毎回新しいビューを作成しますか、それとも既存のビューを数回表示しようとしますか?2番目が正しければ、これを試してみます。

else if (e.Action == NotifyCollectionChangedAction.Remove) {
    foreach (DockableContent content in regionTarget.Items)
        content.Content = null;
    regionTarget.Items.Clear();
}
于 2011-02-14T15:25:40.963 に答える
1

からも削除する必要がある可能性がありregionTargetます。

Snoop を使用して、ビジュアル ツリーから削除されていないものを確認し、要素を削除する必要があるコンテナーを見つけようとすることができます。その他の可能性は、凍結されていないアイコン画像などです。

于 2011-02-14T15:10:15.477 に答える