Я внедряю avalon dock в мое приложение C # wpf, и я заметил странное поведение.Я использую xceed AvalonDock 3.4
После того, как я реализовал сохранение / загрузку макета при запуске приложения путем сериализации, я заметил, что при перетаскивании элемента LayoutAnchorable из вертикального в горизонтальное (или наоборот) вокруг моего LayoutDocument появляется новый layoutPanel.
Примеры 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
}