从文件重新加载布局的 AvalonDock LayoutRoot 示例不显示属性
AvalonDock LayoutRoot example with layout reloaded from file doesn't show properties
我正在评估 AvalonDock 是否适合新项目,并已实施 LayoutRoot class 文档中显示的示例。我添加了在关机和启动时保存和恢复布局的方法。如下图所示,布局已正确恢复,但从文件重新加载布局后,PropertyGrid 不再显示当前文档的内容。我怀疑这与来自 XAML 中另一个元素的内容有关,但无法弄清楚如何在重新加载布局后使其正确显示。我曾尝试在重新加载布局后的不同时间手动调用 PropertyGrid.Update() 但没有任何成功。任何人都可以解释为什么这没有像我预期的那样工作,以及如何让它工作,如果可能的话?
图片 1:PropertyGrid 显示保存前文档 1 中按钮的属性。
图片 2:PropertyGrid 在重新加载保存的布局后不显示文档 1 中按钮的属性。
XAML 来自示例:
<xcad:LayoutRoot x:Name="_layoutRoot" >
<xcad:LayoutPanel Orientation="Horizontal">
<xcad:LayoutAnchorablePane DockWidth="200">
<xcad:LayoutAnchorable ContentId="properties" Title="Properties" CanHide="False" CanClose="False"
AutoHideWidth="240" >
<!--IconSource="Images/property-blue.png"-->
<xctk:PropertyGrid NameColumnWidth="110" Name="pg"
SelectedObject="{Binding ElementName=_layoutRoot, Path=LastFocusedDocument.Content}" />
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
<xcad:LayoutDocumentPaneGroup >
<xcad:LayoutDocumentPane>
<xcad:LayoutDocument ContentId="document1" Title="Document 1" IconSource="Images/document.png" >
<Button Content="Document 1 Content" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</xcad:LayoutDocument>
<xcad:LayoutDocument ContentId="document2" Title="Document 2" IconSource="Images/document.png">
<TextBox Text="Document 2 Content" AcceptsReturn="True"/>
</xcad:LayoutDocument>
</xcad:LayoutDocumentPane>
</xcad:LayoutDocumentPaneGroup >
<xcad:LayoutAnchorablePaneGroup DockWidth="125">
<xcad:LayoutAnchorablePane>
<xcad:LayoutAnchorable ContentId="alarms" Title="Alarms" >
<!--IconSource="../Images/alarm-clock-blue.png"-->
<ListBox>
<s:String>Alarm 1</s:String>
<s:String>Alarm 2</s:String>
<s:String>Alarm 3</s:String>
</ListBox>
</xcad:LayoutAnchorable>
<xcad:LayoutAnchorable ContentId="journal" Title="Journal" >
<RichTextBox>
<FlowDocument>
<Paragraph FontSize="14" FontFamily="Segoe">
This is the content of the Journal Pane.
<LineBreak/>
A
<Bold>RichTextBox</Bold> has been added here
</Paragraph>
</FlowDocument>
</RichTextBox>
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
</xcad:LayoutAnchorablePaneGroup>
</xcad:LayoutPanel>
<xcad:LayoutRoot.LeftSide>
<xcad:LayoutAnchorSide>
<xcad:LayoutAnchorGroup>
<xcad:LayoutAnchorable Title="Agenda" ContentId="agenda" >
<!--IconSource="../Images/address-book-open.png"-->
<TextBlock Text="Agenda Content" Margin="10" FontSize="18" FontWeight="Black" TextWrapping="Wrap"/>
</xcad:LayoutAnchorable>
<xcad:LayoutAnchorable Title="Contacts" ContentId="contacts" >
<!--IconSource="../Images/address-book-pencil.png"-->
<TextBlock Text="Contacts Content" Margin="10" FontSize="18" FontWeight="Black" TextWrapping="Wrap"/>
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorGroup>
</xcad:LayoutAnchorSide>
</xcad:LayoutRoot.LeftSide>
</xcad:LayoutRoot>
重新加载布局的方法:
private void LoadDockingManagerLayout(DockingManager docManager)
{
string layoutFileName = System.IO.Path.Combine(DirAppData, LayoutFileName);
if (System.IO.File.Exists(layoutFileName) == false)
return;
var layoutSerializer = new XmlLayoutSerializer(docManager);
layoutSerializer.Deserialize(layoutFileName);
}
原来重新加载的布局替换了启动时创建的布局。因此对 _layoutRoot 的引用不再有效。所以我不得不像这样重新创建绑定:
Binding myBinding = new Binding("LastFocusedDocument.Content");
myBinding.Source = docManager.Layout;
pg.SetBinding(PropertyGrid.SelectedObjectProperty, myBinding);
您必须附加 DockingManager
实例引发的 LayoutSerializationCallback
,然后在那里设置序列化布局的 Content
。像这样:
var layoutSerializer = new XmlLayoutSerializer(this.DockManager);
layoutSerializer.LayoutSerializationCallback += layoutSerializer_LayoutSerializationCallback;
protected virtual void layoutSerializer_LayoutSerializationCallback(object sender, LayoutSerializationCallbackEventArgs e)
{
try
{
var model = this.Docs.Union(this.Tools).FirstOrDefault(vm => vm.ContentId == e.Model.ContentId);
if (model != null)
{
e.Content = model;
}
else
{
// Log load layout error info
}
}
catch (Exception ex)
{
// Log load layout error info
}
}
我正在评估 AvalonDock 是否适合新项目,并已实施 LayoutRoot class 文档中显示的示例。我添加了在关机和启动时保存和恢复布局的方法。如下图所示,布局已正确恢复,但从文件重新加载布局后,PropertyGrid 不再显示当前文档的内容。我怀疑这与来自 XAML 中另一个元素的内容有关,但无法弄清楚如何在重新加载布局后使其正确显示。我曾尝试在重新加载布局后的不同时间手动调用 PropertyGrid.Update() 但没有任何成功。任何人都可以解释为什么这没有像我预期的那样工作,以及如何让它工作,如果可能的话?
XAML 来自示例:
<xcad:LayoutRoot x:Name="_layoutRoot" >
<xcad:LayoutPanel Orientation="Horizontal">
<xcad:LayoutAnchorablePane DockWidth="200">
<xcad:LayoutAnchorable ContentId="properties" Title="Properties" CanHide="False" CanClose="False"
AutoHideWidth="240" >
<!--IconSource="Images/property-blue.png"-->
<xctk:PropertyGrid NameColumnWidth="110" Name="pg"
SelectedObject="{Binding ElementName=_layoutRoot, Path=LastFocusedDocument.Content}" />
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
<xcad:LayoutDocumentPaneGroup >
<xcad:LayoutDocumentPane>
<xcad:LayoutDocument ContentId="document1" Title="Document 1" IconSource="Images/document.png" >
<Button Content="Document 1 Content" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</xcad:LayoutDocument>
<xcad:LayoutDocument ContentId="document2" Title="Document 2" IconSource="Images/document.png">
<TextBox Text="Document 2 Content" AcceptsReturn="True"/>
</xcad:LayoutDocument>
</xcad:LayoutDocumentPane>
</xcad:LayoutDocumentPaneGroup >
<xcad:LayoutAnchorablePaneGroup DockWidth="125">
<xcad:LayoutAnchorablePane>
<xcad:LayoutAnchorable ContentId="alarms" Title="Alarms" >
<!--IconSource="../Images/alarm-clock-blue.png"-->
<ListBox>
<s:String>Alarm 1</s:String>
<s:String>Alarm 2</s:String>
<s:String>Alarm 3</s:String>
</ListBox>
</xcad:LayoutAnchorable>
<xcad:LayoutAnchorable ContentId="journal" Title="Journal" >
<RichTextBox>
<FlowDocument>
<Paragraph FontSize="14" FontFamily="Segoe">
This is the content of the Journal Pane.
<LineBreak/>
A
<Bold>RichTextBox</Bold> has been added here
</Paragraph>
</FlowDocument>
</RichTextBox>
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
</xcad:LayoutAnchorablePaneGroup>
</xcad:LayoutPanel>
<xcad:LayoutRoot.LeftSide>
<xcad:LayoutAnchorSide>
<xcad:LayoutAnchorGroup>
<xcad:LayoutAnchorable Title="Agenda" ContentId="agenda" >
<!--IconSource="../Images/address-book-open.png"-->
<TextBlock Text="Agenda Content" Margin="10" FontSize="18" FontWeight="Black" TextWrapping="Wrap"/>
</xcad:LayoutAnchorable>
<xcad:LayoutAnchorable Title="Contacts" ContentId="contacts" >
<!--IconSource="../Images/address-book-pencil.png"-->
<TextBlock Text="Contacts Content" Margin="10" FontSize="18" FontWeight="Black" TextWrapping="Wrap"/>
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorGroup>
</xcad:LayoutAnchorSide>
</xcad:LayoutRoot.LeftSide>
</xcad:LayoutRoot>
重新加载布局的方法:
private void LoadDockingManagerLayout(DockingManager docManager)
{
string layoutFileName = System.IO.Path.Combine(DirAppData, LayoutFileName);
if (System.IO.File.Exists(layoutFileName) == false)
return;
var layoutSerializer = new XmlLayoutSerializer(docManager);
layoutSerializer.Deserialize(layoutFileName);
}
原来重新加载的布局替换了启动时创建的布局。因此对 _layoutRoot 的引用不再有效。所以我不得不像这样重新创建绑定:
Binding myBinding = new Binding("LastFocusedDocument.Content");
myBinding.Source = docManager.Layout;
pg.SetBinding(PropertyGrid.SelectedObjectProperty, myBinding);
您必须附加 DockingManager
实例引发的 LayoutSerializationCallback
,然后在那里设置序列化布局的 Content
。像这样:
var layoutSerializer = new XmlLayoutSerializer(this.DockManager);
layoutSerializer.LayoutSerializationCallback += layoutSerializer_LayoutSerializationCallback;
protected virtual void layoutSerializer_LayoutSerializationCallback(object sender, LayoutSerializationCallbackEventArgs e)
{
try
{
var model = this.Docs.Union(this.Tools).FirstOrDefault(vm => vm.ContentId == e.Model.ContentId);
if (model != null)
{
e.Content = model;
}
else
{
// Log load layout error info
}
}
catch (Exception ex)
{
// Log load layout error info
}
}