Wie lade ich automatisch ein Layout in meine AvalonDock-Instanz?

Ich habe AvalonDock 2.0 in meine Anwendung integriert. Ich habe das Dokument und die verankerbaren Quellen an mein Ansichtsmodell gebunden, die mit den richtigen Benutzersteuerelementen über gerendert werdenDataTemplates.

Mit dem kann ich Layouts laden und speichernXmlLayoutSerializer. Ich muss das Laden vordefinierter Layouts bei Bedarf unterstützen (überButtons undICommands). Das funktioniert auch.

Das, was ich nicht arbeiten kann, lädt ein serialisiertes Layout automatisch, wenn dieDockingManager Damit ist das Laden der Ansichtsmodelle und ihrer Ansichten (Benutzersteuerung) abgeschlossen.

Ich habe versucht, mein Layout zu ladenDockingManager.DataContextChanged Aber ich denke, es wird zu früh ausgelöst, da das Layout mit den Dokumenten im ausgeblendeten Bereich geladen wird und die Dokumente in den sichtbaren Bereichen dupliziert werden. Die gerenderten Fenster spiegeln nicht das geladene Layout wider. Wenn das Layout erneut gespeichert wird, werden die Duplikate im ausgeblendeten Bereich gesammelt.

<ad:DockingManager Name="DockingManager"
                   DataContext="{Binding Project}"
                   DataContextChanged="DockingManager_OnDataContextChanged"
                   ActiveContent="{Binding Active}"
                   AnchorablesSource="{Binding Anchorables}"
                   DocumentsSource="{Binding Documents}">
    <ad:DockingManager.Theme>
        <ad:AeroTheme/>
    </ad:DockingManager.Theme>

    <ad:DockingManager.LayoutItemTemplateSelector>
        <views:PanesTemplateSelector>
            <views:PanesTemplateSelector.ChartTemplate>
                <DataTemplate>
                    <views:Chart/>
                </DataTemplate>
            </views:PanesTemplateSelector.ChartTemplate>
            <views:PanesTemplateSelector.WorkspaceTemplate>
                <DataTemplate>
                    <Views:Workspace/>
                </DataTemplate>
            </views:PanesTemplateSelector.WorkspaceTemplate>
            ...
        </views:PanesTemplateSelector>
    </ad:DockingManager.LayoutItemTemplateSelector>

    <ad:DockingManager.LayoutItemContainerStyle>
        <Style TargetType="{x:Type ad:LayoutItem}">
            <Setter Property="Title" Value="{Binding Model.DisplayText}"/>
            <Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
        </Style>
    </ad:DockingManager.LayoutItemContainerStyle>

    <ad:LayoutRoot>
        <!--<ad:LayoutPanel>
            <ad:LayoutDocumentPane/>
            <ad:LayoutAnchorablePane/>
        </ad:LayoutPanel>-->
    </ad:LayoutRoot>
</ad:DockingManager>

... und der Code-Behind ...

private void SaveLayout() {
    if (this.DataContext == null)
        return;
    var xmlLayoutSerializer = new XmlLayoutSerializer(this.DockingManager);
    var stringBuilder = new StringBuilder();
    using (var textWriter = new StringWriter(stringBuilder))
        xmlLayoutSerializer.Serialize(textWriter);
    var serialized = stringBuilder.ToString();
    (this.DataContext as dynamic).XmlSerializedAndEscapedLayout = HttpUtility.HtmlEncode(serialized);
}
private void LoadLayout()
{
    if (DataContext == null)
        return;
    var encoded = (DataContext as dynamic).XmlSerializedAndEscapedLayout;
    var window = Window.GetWindow(this);
    window.Closing += (sender, args) => SaveLayout();
    if (String.IsNullOrWhiteSpace(encoded))
        return;
    var serialized = HttpUtility.HtmlDecode(encoded);
    var xmlLayoutSerializer = new XmlLayoutSerializer(DockingManager);
    using (var stringReader = new StringReader(serialized))
        xmlLayoutSerializer.Deserialize(stringReader);
}
private void DockingManager_OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue != null) // A type check here would be best, I know.
        LoadLayout();
}

... und das Ansichtsmodell ...

public class ProjectViewModel
{
    public IModel Model { get; private set; }
    public String SerializedLayout { get; set; }
    public ViewModelBase Active { get; set; }
    private readonly ObservableCollection<ViewModelBase> documents;
    public ReadOnlyObservableCollection<ViewModelBase> Documents { get; private set; }
    private readonly ObservableCollection<ViewModelBase> anchorables;
    public ReadOnlyObservableCollection<ViewModelBase> Anchorables { get; private set; }

    public ProjectViewModel(String filePath, String serializedLayout)
    {
        SerializedLayout = serializedLayout;
        using (var fileStream = new FileStream(filePath, FileMode.Open))
        {
            IModelRepository modelRepository = Ioc.DependencyInjectionContainer.DefaultContainer.Resolve<IModelRepository>();
            Model = modelRepository.Load(fileStream);
        }
        documents = new ObservableCollection<ViewModelBase>();
        anchorables = new ObservableCollection<ViewModelBase>();
        documents.Add(new Workspace());
        anchorables.Add(new RiskLimitsViewModel(Model.RiskLimits));
        ...
        Documents = new ReadOnlyObservableCollection<ViewModelBase>(documents);
        Anchorables = new ReadOnlyObservableCollection<ViewModelBase>(anchorables);
    }
}

Jede Einsicht wäre sehr dankbar. Vielen Dank!

Antworten auf die Frage(2)

Ihre Antwort auf die Frage