Так что я, наверное, нашел решение.
У меня есть несколько панелей (назовите их MapPanel), и их содержимое не загружается, когда макет восстанавливается из XML. В моем случае у меня есть приложение, в котором есть несколько документов и вкладок, и, кроме того, пользователь может загрузить дополнительные данные для отображения карт.
И мне нужно было восстановить макет этих карт, когда пользователь их загрузит. (нажмите кнопку, выберите c, куда загружать карты и т.д. c)
У меня есть класс stati c с именем LayoutSaveLoadUtil (как описано в codeproject), когда у меня есть дополнительный список MapPanelsStorage типа LayoutAnchorable. К этому списку я сохраняю все макеты, в которых отсутствует контент при восстановлении макета, а ContentId имеет префикс c. Это говорит мне, что это MapPanel. Затем я создаю фиктивный контент, назначаю его этой панели и устанавливаю для его видимости значение false (поэтому панель невидима)
(это вызывается в layoutSerializationCallback)
private object ReloadItem(object item)
{
object ret = null;
switch (item)
{
case LayoutAnchorable anchorable:
//list of tools windows
ret = Manager.Tools.FirstOrDefault(i => i.ContentId == anchorable.ContentId);
if(ret == null && anchorable.ContentId.StartsWith(MapPanel.MapPanelPrefix))
{
//when layoutAnchorable is MapPanel (has MapPanel prefix) and its content is loaded yet
//store its layout into list to restore it later (when content is loaded)
MapPanelsStorage.Add(anchorable);
//Set anchorable visibility to false
anchorable.IsVisible = false;
//return dummy model for avalondock layout serialization
ret = new EmptyMapViewModel();
}
break;
case LayoutDocument document:
// list of restored documents
ret = Manager.Documents.FirstOrDefault(i => i.ContentId == document.ContentId);
break;
default:
throw new NotImplementedException("Not implemented type of AD item ");
}
return ret;
}
Затем в BeforeInsertAnchorable ( вызывается при добавлении новой панели в макет) Я проверяю, является ли содержимое панели MapPanel, ищите сохраненный макет, пытаюсь найти родительский (LayoutAnchorablePane / LayoutDocumentPane), а затем добавить его вместо панели DummyHidden и просто удалить его из хранилища.
//hacky hacky to restore map panel layout when map is opened after layout is loaded
//in layout deserialization, deserialize layout for MapPanels that hasnt DataModels yet with DummyModel to preserve their layout
if (anchorableToShow.Content is MapPanel mappanel)
{
var storedMapsLayout = LayoutSaveLoadUtil.Instance.MapPanelsStorage;
//check if Map panel has stored layout from previous layout deserialization
var matchingAnchorable = storedMapsLayout.FirstOrDefault(m => m.ContentId == mappanel.ContentId);
if (matchingAnchorable != null)
{
//make preserved layout visible, so its parent and etc is restored. Without this, correct parent LayoutGroup isnt found
matchingAnchorable.IsVisible = true;
LayoutAnchorablePane matchingAnchorablePane;
LayoutDocumentPane matchingDocumentPane;
//find parent layoutGroup. This can be LayoutAnchorablePane or LayoutDocumentPane
if ((matchingAnchorablePane = matchingAnchorable.FindParent<LayoutAnchorablePane>()) != null)
{
//add new panel into layoutGroup with correct layout
matchingAnchorablePane.Children.Add(anchorableToShow);
//remove old dummy panel
matchingAnchorablePane.RemoveChild(matchingAnchorable);
//remove restored layout from storage
storedMapsLayout.Remove(matchingAnchorable);
return true;
}
else if ((matchingDocumentPane = matchingAnchorable.FindParent<LayoutDocumentPane>()) != null)
{
//add new panel into layoutGroup with correct layout
matchingDocumentPane.Children.Add(anchorableToShow);
//remove old dummy panel
matchingDocumentPane.RemoveChild(matchingAnchorable);
//remove restored layout from storage
storedMapsLayout.Remove(matchingAnchorable);
return true;
}
else
{
matchingAnchorable.IsVisible = false;
}
}
}