我在C#wpf应用程序中实现avalon扩展坞,我注意到了奇怪的行为。我正在使用xceed AvalonDock 3.4
通过序列化在应用启动时实现布局保存/加载后,我注意到当我将LayoutAnchorable元素从垂直拖动到水平(反之亦然)时,新的layoutPanel出现在我的LayoutDocument周围。
XML示例和代码如下。我很粗鲁,我做错了什么。当我在avalonDock 2.0中使用相同的代码时,它可以工作,并且没有出现备用的LayoutPanel,但是我认为即使使用新的avalondock,它也应该可以工作。
在首次启动应用后,Layou xml导出看起来像(对我来说似乎还可以)
<LayoutRoot>
<RootPanel Orientation="Vertical">
<LayoutPanel Orientation="Horizontal">
<LayoutDocumentPane>
<LayoutDocument Title="level" IsSelected="True" IsLastFocusedDocument="True" ContentId="level" CanClose="False" LastActivationTimeStamp="10/25/2018 20:11:41" />
</LayoutDocumentPane>
</LayoutPanel>
<LayoutAnchorablePane Name="ToolsPane" DockHeight="25">
<LayoutAnchorable AutoHideMinWidth="100" AutoHideMinHeight="100" Title="Nodes" IsSelected="True" ContentId="nodes" CanClose="False" />
<LayoutAnchorable AutoHideMinWidth="100" AutoHideMinHeight="100" Title="Properties" ContentId="properties" CanClose="False" />
</LayoutAnchorablePane>
</RootPanel>
<TopSide />
<RightSide />
<LeftSide />
<BottomSide />
<FloatingWindows />
<Hidden />
</LayoutRoot>
但是当我将LayoutAnchorable拖动到另一侧时,出现LayoutPanel。当我多次拖动LayoutAnchorable时,会出现多个LayoutPanels。
<LayoutRoot>
<RootPanel Orientation="Horizontal">
<LayoutPanel Orientation="Vertical">
<LayoutPanel Orientation="Horizontal">
<LayoutDocumentPane>
<LayoutDocument Title="level" IsSelected="True" IsLastFocusedDocument="True" ContentId="level" CanClose="False" LastActivationTimeStamp="10/25/2018 20:12:38" />
</LayoutDocumentPane>
</LayoutPanel>
</LayoutPanel>
<LayoutAnchorablePaneGroup Orientation="Horizontal" DockWidth="392" DockHeight="79" FloatingWidth="794" FloatingHeight="89" FloatingLeft="559" FloatingTop="422">
<LayoutAnchorablePane DockHeight="79" FloatingWidth="794" FloatingHeight="89" FloatingLeft="559" FloatingTop="422">
<LayoutAnchorable AutoHideMinWidth="100" AutoHideMinHeight="100" Title="Nodes" IsSelected="True" ContentId="nodes" FloatingLeft="559" FloatingTop="422" FloatingWidth="794" FloatingHeight="89" CanClose="False" LastActivationTimeStamp="10/25/2018 20:12:38" />
<LayoutAnchorable AutoHideMinWidth="100" AutoHideMinHeight="100" Title="Properties" ContentId="properties" FloatingLeft="559" FloatingTop="422" FloatingWidth="794" FloatingHeight="89" CanClose="False" />
</LayoutAnchorablePane>
</LayoutAnchorablePaneGroup>
</RootPanel>
<TopSide />
<RightSide />
<LeftSide />
<BottomSide />
<FloatingWindows />
<Hidden />
</LayoutRoot>
我的阿瓦隆码头xaml
<dock:DockingManager helper:AvalonDockLayoutSerializer.LoadLayoutCommand="{Binding Source={x:Static VM:QuestSystemViewModel.Instance}, Path=ADLayout.LoadLayoutCommand}"
helper:AvalonDockLayoutSerializer.SaveLayoutCommand="{Binding Source={x:Static VM:QuestSystemViewModel.Instance}, Path=ADLayout.SaveLayoutCommand}"
ActiveContent="{Binding Source={x:Static VM:QuestSystemViewModel.Instance}, Path=ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}"
AnchorablesSource="{Binding Source={x:Static VM:QuestSystemViewModel.Instance}, Path=Tools}"
DocumentsSource="{Binding Source={x:Static VM:QuestSystemViewModel.Instance}, Path=Documents}">
<dock:DockingManager.LayoutItemContainerStyleSelector>
<helper:PanesStyleSelector>
<helper:PanesStyleSelector.DocumentStyle>
<Style TargetType="{x:Type dock:LayoutDocumentItem}">
<Setter Property="Title" Value="{Binding Model.Title}" />
<Setter Property="ContentId" Value="{Binding Model.Title}" />
<Setter Property="CanClose" Value="{Binding Model.CanClose}" />
<Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}" />
</Style>
</helper:PanesStyleSelector.DocumentStyle>
<helper:PanesStyleSelector.AnchorableStyle>
<Style TargetType="{x:Type dock:LayoutAnchorableItem}">
<Setter Property="Title" Value="{Binding Model.Title}" />
<Setter Property="ContentId" Value="{Binding Model.ContentId}" />
<Setter Property="CanClose" Value="{Binding Model.CanClose}" />
<Setter Property="CanHide" Value="{Binding Model.CanHide}" />
</Style>
</helper:PanesStyleSelector.AnchorableStyle>
</helper:PanesStyleSelector>
</dock:DockingManager.LayoutItemContainerStyleSelector>
<dock:DockingManager.DocumentHeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock MaxWidth="100"
VerticalAlignment="Center"
Text="{Binding Title}"
TextTrimming="CharacterEllipsis" />
</StackPanel>
</DataTemplate>
</dock:DockingManager.DocumentHeaderTemplate>
<dock:DockingManager.Resources>
<DataTemplate DataType="{x:Type VM:ChartViewModel}">
<cntrl:ChartControl DataContext="{Binding}" />
</DataTemplate>
<DataTemplate DataType="{x:Type containers:AnchorableContainer}">
<TextBlock Text="{Binding Content}" />
</DataTemplate>
</dock:DockingManager.Resources>
<dock:DockingManager.LayoutUpdateStrategy>
<helper:LayoutInitializer />
</dock:DockingManager.LayoutUpdateStrategy>
<dock:LayoutRoot>
<dock:LayoutPanel Orientation="Vertical">
<dock:LayoutPanel>
<dock:LayoutDocumentPane />
</dock:LayoutPanel>
<dock:LayoutAnchorablePane Name="ToolsPane" />
</dock:LayoutPanel>
</dock:LayoutRoot>
</dock:DockingManager>
我非常确定它与序列化无关,并且在拖动后立即显示LayoutPanels,但是请确保我将代码附加到序列化中
public ICommand LoadLayoutCommand => new RelayCommand<DockingManager>(param => LoadDockingManagerLayout(param));
public ICommand SaveLayoutCommand => new RelayCommand<string>(param => SaveDockingManagerLayout(param));
#region LoadLayout
private void LoadDockingManagerLayout(DockingManager docManager)
{
String layoutFileName = Path.Combine(DirAppData, LayoutFileName);
if (!File.Exists(layoutFileName))
{
return;
}
var layoutSerializer = new XmlLayoutSerializer(docManager);
layoutSerializer.LayoutSerializationCallback += (s, args) =>
{
// This can happen if the previous session was loading a file
// but was unable to initialize the view ...
if (args.Model.ContentId == null)
{
args.Cancel = true;
return;
}
ReloadContentOnStartUp(args);
};
layoutSerializer.Deserialize(layoutFileName);
}
private void ReloadContentOnStartUp(LayoutSerializationCallbackEventArgs args)
{
string sId = args.Model.ContentId;
// Empty Ids are invalid but possible if aaplication is closed with File>New without edits.
if (string.IsNullOrWhiteSpace(sId) == true)
{
args.Cancel = true;
return;
}
args.Content = ReloadDocument(args.Model.ContentId);
if (args.Content == null)
args.Cancel = true;
}
private object ReloadDocument(string path)
{
object ret = null;
if (!string.IsNullOrWhiteSpace(path))
{
switch (path)
{
case "nodes":
ret = QuestSystemViewModel.Instance.NodePanel;
break;
case "properties":
ret = QuestSystemViewModel.Instance.PropertiesPanel;
break;
default:
ret = null;
break;
}
}
return ret;
}
#endregion
#region saveLayout
private void SaveDockingManagerLayout(string xmlLayout)
{
// Create XML Layout file on close application (for re-load on application re-start)
if (xmlLayout == null)
return;
string fileName = Path.Combine(DirAppData, LayoutFileName);
File.WriteAllText(fileName, xmlLayout);
}
#endregion
}