Load and save layout of anchorables - Binding of Visibility
Asked Answered
C

1

23

I am facing the problem that I cannot open an anchorable of type X after I have loaded my old layout. This happens only when I have closed the anchorable of type X before saving the layout.

Does anyone have a similar problem with AvalonDock? Is this a bug of AvalonDock? After years of debugging, I fear that the binding <Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/> doesn't get updated correctly in the view, when changing IsActive in the ViewModel. AvalonDock should be responsible for this task. But maybe the problem is the loading and saving of the layout?

The code

View

I am loading the saved layout of my anchorables (= tool windows) in the Loaded Event of my DockingManager in my View like this (simplified):

string savedLayout = Properties.Settings.Default.Layout;
XmlDocument doc = new XmlDocument();
doc.LoadXml(savedLayout);

// very simplified code. load saved xml layout and add anchorables to the dockmanager
doc.SelectNodes("//LayoutAnchorable").OfType<XmlNode>().ToList().ForEach(anchorable =>
{
    this.DockManager.AnchorablesSource.Add(anchorable);
});

I am saving the current layout of my anchorables in the Closing Event of my MainWindow in my View like this (simplified):

XmlDocument doc = new XmlDocument();
XmlLayoutSerializer xmlLayoutSerializer = new XmlLayoutSerializer(this.DockManager);

using (MemoryStream stream = new MemoryStream())
{
    xmlLayoutSerializer.Serialize(stream);
    stream.Seek(0, SeekOrigin.Begin);
    doc.Load(stream);
}
// here happens some magic. i think this code is not responsible for my problem
Properties.Settings.Default.Layout = doc.OuterXml;

The ViewModel is bound to the ViewModel in the XAML like this (simplified):

<xcad:DockingManager x:Name="DockManager" AnchorablesSource="{Binding Tools}" Loaded="DockManager_Loaded">
    <xcad:DockingManager.LayoutItemContainerStyle>
        <Style TargetType="{x:Type dockctrl:LayoutItem}">
            <Setter Property="Title" Value="{Binding Model.ContentId}" />
            <Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}" />
            <Setter Property="CanClose" Value="{Binding Model.CanClose, Mode=TwoWay}" />
            <Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={StaticResource Bool2vis}, ConverterParameter={x:Static Visibility.Hidden}}"/>
            <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}" />
            <Setter Property="IconSource" Value="{Binding Model.IconSource}" />
            <Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/>
            <Setter Property="ContentId" Value="{Binding Model.ContentId}" />
        </Style>
    </xcad:DockingManager.LayoutItemContainerStyle>
[...]

ViewModel

The anchorable is opened in the ViewModel of the MainWindow. Here is the example code for the messages:

public ObservableCollection<ToolBoxViewModelBase> Tools { get; } = new ObservableCollection<ToolBoxViewModelBase>();

public MainWindowViewModel()
{
    // [...]
    this.MessagesWindow = new MessagesWindowViewModel();
    SimpleIoc.Default.Register<MessagesWindowViewModel>(() => this.MessagesWindow);
    this.ShowMessagesWindowCommand = new RelayCommand(() => this.OpenToolBox(this.MessagesWindow));
    // [...]
}

public void OpenToolBox<T>(T viewModel) where T : ToolBoxViewModelBase
{
    // [...]
    viewModel.IsVisible = true;
    viewModel.IsActive = true;
    // [...]
}

Just let me know if you need more information or wether i have missed to add some code!

Cathey answered 16/8, 2016 at 11:56 Comment(3)
Did you ever solve this issue?Madonia
@Madonia Yes, I did.Ethanethane
A giraffe said to another giraffe. "hi how r u?". The other one, after keeping silent for half an hour, replied: "I'm good. thanks." The first said, "why did u take so long?" The second said, "I was swallowing saliva." Just sayin... :)Madonia
B
0

Maybe I misunderstood you question but... IsActive property is not used for opening a tool saved into the layout. That property is used to set a Tool as active (focused). In order to open the tool saved into the layout you should handle the layoutSerializer_LayoutSerializationCallback attached the Something like this:

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    
        }
    }
Ber answered 23/5, 2018 at 17:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.