Prism RegionAdapter - удаление и добавление вида - PullRequest
2 голосов
/ 14 февраля 2011

У меня есть решение prism / wpf / mef, которое содержит AvalonDock.Я создал класс 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));
    }

Есть идеи, что мне не хватает?

Ответы [ 3 ]

2 голосов
/ 14 февраля 2011

Вы создаете новый вид каждый раз или пытаетесь показать существующий вид несколько раз?Если второе правильно, я бы попробовал это:

else if (e.Action == NotifyCollectionChangedAction.Remove) {
    foreach (DockableContent content in regionTarget.Items)
        content.Content = null;
    regionTarget.Items.Clear();
}
2 голосов
/ 14 февраля 2011

Вместо обработки события Closed (которое могло потерять ссылку на базовое представление) я обрабатываю событие Closing.

Это сработало, однако, когда я попытался повторно открыть вкладку, она отображала тот же экземпляр. После прочтения этого В Composite WPF (Prism), чем отличается IRegion.Add от IRegionManager.RegisterViewWithRegion? Я изменил это:

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

к этому:

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

Мне все еще нужно провести некоторые исследования с помощью Prism / avalondock, чтобы убедиться, что утечек памяти не будет, но на данный момент он работает.

1 голос
/ 14 февраля 2011

Вероятно, вам также потребуется удалить его из regionTarget.

Вы можете использовать Snoop, чтобы увидеть, что не было удалено из дерева визуалов, а затем попытаться найти, какоеКонтейнер, из которого нужно удалить свой элемент.Другие возможности, такие как незамерзающее изображение значка и т. Д.

...