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

23

我遇到了一个问题,就是在加载旧布局后,无法打开类型为X的可锚定窗口。只有在保存布局之前关闭类型为X的可锚定窗口时才会出现这种情况。

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

代码

视图

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

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

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

如果您需要更多信息或者我遗漏了一些代码,请告诉我!


1
你解决了这个问题吗? - dotNET
@dotNET 是的,我做到了。 - ˈvɔlə
3
一只长颈鹿对另一只说:“嗨,你好吗?” 另一只保持沉默半个小时后回答道:“我很好,谢谢。” 第一只问:“为什么这么久才回复?” 第二只说:“我在咽口水。”就这样... :) - dotNET
1个回答

0
也许我误解了你的问题,但是... 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    
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接