从文件重新加载布局的 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    
    }
}