C# Avalondock-某些面板的延迟布局恢复

C# Avalondock-某些面板的延迟布局恢复,c#,mvvm,avalondock,C#,Mvvm,Avalondock,我使用的加载/保存布局方式与上所述类似。捕获LayoutSerializationCallback事件并尝试查找LayoutItem的相应viewModel private void LayoutSerializer_LayoutSerializationCallback(object sender, LayoutSerializationCallbackEventArgs e) { // This can happen if the previous s

我使用的加载/保存布局方式与上所述类似。捕获LayoutSerializationCallback事件并尝试查找LayoutItem的相应viewModel

private void LayoutSerializer_LayoutSerializationCallback(object sender, LayoutSerializationCallbackEventArgs e)
        {
            // This can happen if the previous session was loading a file
            // but was unable to initialize the view ...
            if (string.IsNullOrWhiteSpace(e.Model.ContentId) || (e.Content = ReloadItem(e.Model)) == null)
            {
                e.Cancel = true;
                return;
            }
        }

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))
            {

                MapPanels.Add(anchorable);
            }
            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;

}
在反序列化/恢复布局时,如果所有ViewModel都可用,则此操作非常有效

但我在考虑延迟布局恢复之类的事情。就我而言,我一开始就有一些文档和一些面板。但是可能会有一些面板(称为MapPanel)稍后加载(viewModels将在将来加载)。我不知道如何恢复这些面板的布局

对于这种情况,我有列表映射面板来存储在avalondock layout load加载的锚点,并尝试在ILayoutUpdateStregy中的BeforeInsertAnchorable中恢复它们。但当我调试它时,存储的LayoutActionTable有不同的父级存储它。所以我假设在LayoutSerializationCallback中取消(e.Cancel=true)之后,不知何故修改了NotRestored anchorable

public bool BeforeInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableToShow, ILayoutContainer destinationContainer)
        {
            if (anchorableToShow.Content is ToolPanel tool)
            {

                if(tool is MapPanel)
                {
                    anchorableToShow = LayoutSaveLoadUtil.Instance.MapPanels.FirstOrDefault(mp => mp.ContentId == anchorableToShow.ContentId);
                }

                var destPane = destinationContainer as LayoutAnchorablePane;
                if (destinationContainer != null && destinationContainer.FindParent<LayoutFloatingWindow>() != null)
                    return false;


                var dockLeftPane = layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault(d => d.Name == tool.PreferredLocation + "Pane");
                if (dockLeftPane != null)
                {
                    dockLeftPane.Children.Add(anchorableToShow);
                    return true;
                }

                return false;
            }

            return false;

        }
public bool-before-insertanchorable(LayoutRoot布局、LayoutAnchorable-anchorableThow、ILayoutContainer-destinationContainer)
{
if(anchorableToShow.Content是工具面板工具)
{
如果(工具是MapPanel)
{
anchorableToShow=LayoutSaveLoadUtil.Instance.MapPanels.FirstOrDefault(mp=>mp.ContentId==anchorableToShow.ContentId);
}
var destPane=作为LAYOUTANCHRABLEPANE的目的容器;
if(destinationContainer!=null&&destinationContainer.FindParent()!=null)
返回false;
var dockLeftPane=layout.degents().OfType().FirstOrDefault(d=>d.Name==tool.PreferredLocation+“窗格”);
if(dockLeftPane!=null)
{
dockLeftPane.Children.Add(锚定显示);
返回true;
}
返回false;
}
返回false;
}

所以我很好奇什么是实现这一目标的正确方法。我也在考虑在MapPanel加载后(再次)恢复布局,但我不知道如何跳过所有其他布局项。那么,有没有可能恢复单个固定位置、浮动的父对象、停靠、大小等…?

所以我可能找到了解决方案

我有一些面板(称为MapPanel),当从XML恢复布局时,它们的内容不会加载。在我的例子中,我有一个应用程序,它有一些文档和选项卡,在传统模式中,用户可以加载传统数据来显示地图

当用户加载这些地图时,我需要恢复它们的布局。(单击按钮,选择加载地图的位置等)

我有一个名为LayoutSaveLoadUtil的静态类(如codeproject中所述),当我有LayoutAchorable类型的传统列表映射面板存储时。在此列表中,我存储了布局还原时缺少内容的所有布局,并且ContentId具有特定前缀。这告诉我这是地图面板。然后我创建一个虚拟内容,将其分配给该面板,并将其可见性设置为false(因此面板不可见)

(这在layoutSerializationCallback中调用)

然后在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;
        }
    }
}
//加载布局后打开地图时还原地图面板布局的hacky hacky
//在布局反序列化中,使用DummyModel反序列化尚未建立数据模型的地图面板的布局,以保留其布局
如果(anchorableToShow.Content是MapPanel MapPanel)
{
var storedMapsLayout=LayoutSaveLoadUtil.Instance.MapPanelsStorage;
//检查“地图面板”是否存储了上一个布局反序列化中的布局
var matchingAnchorable=storedMapsLayout.FirstOrDefault(m=>m.ContentId==mappanel.ContentId);
if(匹配Anchorable!=null)
{
//使保留的布局可见,以便还原其父级和etc。否则,将找不到正确的父级布局组
matchingAnchorable.IsVisible=true;
LayoutAnchorablePane匹配AnchorablePane;
布局文档窗格匹配文档窗格;
//查找父layoutGroup。这可以是LayoutAchrablePane或LayoutDocumentPane
if((matchingAnchorablePane=matchingAnchorable.FindParent())!=null)
{
//将新面板添加到布局正确的layoutGroup中
匹配AnchorablePane.Children.Add(AnchorableThow);
//拆下旧的模拟面板
匹配AnchorablePane.RemoveChild(匹配Anchorable);
//从存储器中删除还原的布局
storedMapsLayout.Remove(匹配Anchorable);
返回true;
}
如果((matchingDocumentPane=matchingAnchorable.FindParent())!=null,则为else
{
//将新面板添加到布局正确的layoutGroup中
matchingDocumentPane.Children.Add(anchorableToShow);
//拆下旧的模拟面板
匹配DocumentPane.RemoveChild(匹配Anchorable);
//从存储器中删除还原的布局
storedMapsLayout.Remove(匹配Anchorable);
返回true;
}
其他的
{
matchingAnchorable.IsVisible=false;
}
}
}
//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;
        }
    }
}