Jak automatycznie załadować układ do mojej instancji AvalonDock?

Zintegrowałem AvalonDock 2.0 z moją aplikacją. Dokument i zakotwiczone źródła powiązałem z moim modelem widoku, który jest renderowany za pomocą odpowiednich elementów sterujących użytkownikaDataTemplates.

Mogę ładować i zapisywać układy za pomocąXmlLayoutSerializer. Muszę obsługiwać ładowanie predefiniowanych układów na żądanie (przezButtons iICommands). To również działa.

Rzeczą, której nie mogę uzyskać, jest automatyczne ładowanie serializowanego układu, gdyDockingManager trwa ładowanie modeli widoku i ich widoków (formanty użytkownika).

Próbowałem wczytać mój układDockingManager.DataContextChanged ale myślę, że odpala się zbyt wcześnie, ponieważ układ ładuje dokumenty z ukrytej sekcji i duplikuje dokumenty w widocznych sekcjach. Wyrenderowane panele nie odzwierciedlają załadowanego układu i po ponownym zapisaniu układu duplikaty są gromadzone w ukrytej sekcji.

<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>

... i kod-za ...

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();
}

... I model widoku ...

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);
    }
}

Każdy wgląd zostałby bardzo doceniony. Dzięki!

questionAnswers(2)

yourAnswerToTheQuestion