加载和保存锚定布局 - 可见性绑定

Posted

技术标签:

【中文标题】加载和保存锚定布局 - 可见性绑定【英文标题】:Load and save layout of anchorables - Binding of Visibility 【发布时间】:2016-08-16 11:56:49 【问题描述】:

我面临的问题是在加载旧布局后无法打开 X 类型的可锚定对象。仅当我在保存布局之前关闭类型 X 的可锚定对象时才会发生这种情况。

有人对AvalonDock 有类似的问题吗?这是 AvalonDock 的错误吗?经过多年的调试,我担心在 ViewModel 中更改 IsActive 时绑定 <Setter Property="IsActive" Value="Binding Model.IsActive, Mode=TwoWay"/> 不会在视图中正确更新。 AvalonDock 应该负责这个任务。但也许问题在于布局的加载和保存?

代码

查看

我在我的视图中的DockingManagerLoaded 事件中加载已保存的可锚定布局(= 工具窗口),如下所示(简化):

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

我在我的视图中将我的锚定对象的当前布局保存在我的MainWindowClosing 事件中,如下所示(简化):

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;

ViewModel 绑定到 XAML 中的 ViewModel,如下所示(简化):

<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>
[...]

视图模型

anchorable 在 MainWindow 的 ViewModel 中打开。以下是消息的示例代码:

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;
    // [...]

如果您需要更多信息,或者我错过了添加一些代码,请告诉我!

【问题讨论】:

你解决过这个问题吗? @dotNET 是的,我做到了。 一只长颈鹿对另一只长颈鹿说。 “嗨,你好么?”。另一个人沉默了半个小时后,回复道:“我很好,谢谢。”第一个说:“你为什么花了这么长时间?”第二个说:“我在吞口水。”只是说... :) 【参考方案1】:

也许我误解了你的问题,但是...IsActive 属性不用于打开保存到布局中的工具。该属性用于将工具设置为活动(聚焦)。为了打开保存到布局中的工具,您应该处理附加的layoutSerializer_LayoutSerializationCallback 像这样的:

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    
        
    

【讨论】:

以上是关于加载和保存锚定布局 - 可见性绑定的主要内容,如果未能解决你的问题,请参考以下文章

绑定到可见性属性时动画不正确(奇数)

设置可见性时 XML 列表视图重叠元素

将 XAML 中的可见性绑定到可见性属性

在异步任务中更改 onPostexecute 中的可见性设置

DataGridTextColumn 可见性绑定

Silverlight DataGridTextColumn 绑定可见性