gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 10:31:36 26 4
gpt4 key购买 nike

我使用的加载/保存布局类似于CodeProject所述。捕获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;

}

反序列化/还原布局时,当我有所有可用的ViewModels时,这可以很好地工作。

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

对于这种情况,我具有List MapPanels来存储在avalondock布局加载时加载的可 anchor 定 map ,并尝试在ILayoutUpdateStrategy的BeforeInsertAnchorable中还原它们。但是当我调试它时,存储的LayoutAnchorable具有存储一个的不同父项。因此,我假设在LayoutSerializationCallback中取消(e.Cancel = true)后,会以某种方式修改无法恢复的 anchor 定。
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;

}

所以我很好奇实现此目标的正确方法。我还考虑过在加载MapPanel之后(再次)恢复布局,但是我不知道如何跳过所有其他LayoutItems。那么,是否有可能恢复单个Anchorable位置, float 父对象,停靠,尺寸等...?

最佳答案

所以我大概想出了解决方案。

我有一些面板(称为MapPanel),并且从XML恢复布局时不会加载theyr的内容。以我为例,我有一个具有一些文档和选项卡的应用程序,并且在其他情况下,用户可以加载其他数据以显示 map 。

当用户加载 map 时,我需要恢复此 map 的布局。 (单击按钮,选择在哪里加载 map 等)

当我有LayoutAnchorable类型的附加列表MapPanelsStorage时,我有一个名为LayoutSaveLoadUtil的静态类(如代码项目中所述)。在此列表中,我存储了在布局还原中缺少内容且ContentId具有特定前缀的所有布局。这告诉我是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;
}
}
}

关于c# - Avalondock-某些面板的布局恢复延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60388485/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com