Prism RegionAdapter - удаление и добавление вида
У меня есть решение prism/wpf/mef, которое содержит AvalonDock. Я создал RegionAdapterBase<Pane>
класс, который обрабатывает создание и удаление панелей из AvalonDock.
Вот проблема, с которой я сталкиваюсь:
- Я нажимаю кнопку в моем меню, и представление регистрируется в регионе и отображается в моем
DocumentPane
- Я нажимаю кнопку закрытия в AvalonDock, чтобы закрыть вкладку и удалить вид
- Я нажимаю ту же кнопку меню, чтобы добавить его снова
- Я получаю ошибку:
"Указанный элемент уже является логическим дочерним элементом другого элемента. Сначала отключите его".
Итак... это говорит мне, что что-то осталось, что мне нужно удалить, но я не могу понять, где это. Вот некоторый код из моего 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 ответа
Вместо обработки события 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, чтобы убедиться, что не будет утечек памяти, но на данный момент, похоже, он работает.
Вы создаете новый вид каждый раз или пытаетесь показать существующий вид несколько раз? Если второе правильно, я бы попробовал это:
else if (e.Action == NotifyCollectionChangedAction.Remove) {
foreach (DockableContent content in regionTarget.Items)
content.Content = null;
regionTarget.Items.Clear();
}
Вы, вероятно, должны удалить его из regionTarget
также.
Вы можете использовать Snoop, чтобы увидеть, что не было удалено из дерева визуалов, а затем попытаться найти контейнер, из которого нужно удалить свой элемент. Другие возможности, такие как незамерзающее изображение значка и т. Д.