在AvalonDock中绑定layoutanchoritemvisibility

本文关键字:layoutanchoritemvisibility 绑定 AvalonDock | 更新日期: 2023-09-27 18:03:03

我试图将LayoutAnchorableItemVisibility绑定到ViewModel中的布尔值,以便我可以以编程方式显示和隐藏可锚定的:

<UserControl.Resources>
    <avalon:BoolToVisibilityConverter x:Key="btvc"/>
</UserControl.Resources>
<avalon:DockingManager>
    <avalon:DockingManager.LayoutItemContainerStyleSelector>
        <ws:WorkspaceStyleSelector>
            <ws:WorkspaceStyleSelector.AnchorableStyle>
                <Style TargetType="{x:Type avalon:LayoutAnchorableItem}">
                    <!-- ... -->
                    <Setter Property="Visibility" Value="{Binding Model.IsVisible, Converter={StaticResource btvc}, Mode=TwoWay}"/>
                </Style>
            </ws:WorkspaceStyleSelector.AnchorableStyle>
        </ws:WorkspaceStyleSelector>
    </avalon:DockingManager.LayoutItemContainerStyleSelector>
    <!-- ... -->
</avalon:DockingManager>

但是,每当我隐藏一个可锚定对象时,就会抛出一个异常:

对象引用未设置为实例。

at Xceed.Wpf.AvalonDock.Layout.LayoutContent.Close() in ...'Xceed.Wpf.AvalonDock'Layout'LayoutContent.cs:line 346
at Xceed.Wpf.AvalonDock.Controls.LayoutItem.OnVisibilityChanged() in ...'Xceed.Wpf.AvalonDock'Controls'LayoutItem.cs:line 310
at Xceed.Wpf.AvalonDock.Controls.LayoutAnchorableItem.OnVisibilityChanged() in ...'Xceed.Wpf.AvalonDock'Controls'LayoutAnchorableItem.cs:line 299
at Xceed.Wpf.AvalonDock.Controls.LayoutItem.OnVisibilityChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) in ...'Xceed.Wpf.AvalonDock'Controls'LayoutItem.cs:line 303
at Xceed.Wpf.AvalonDock.Controls.LayoutItem.<.cctor>b__1(DependencyObject s, DependencyPropertyChangedEventArgs e) in ...'Xceed.Wpf.AvalonDock'Controls'LayoutItem.cs:line 37
at System.Windows.PropertyChangedCallback.Invoke(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
...

在注释掉绑定到可见性之后,锚定被隐藏。

在AvalonDock中绑定layoutanchoritemvisibility

br

需要在Binding中添加值为Visibility.HiddenConverterParameter:

<Setter Property="Visibility" Value="{Binding Model.IsVisible, ConverterParameter={x:Static Visibility.Hidden}, Converter={StaticResource btvc}, Mode=TwoWay}"/>

转换器参数为布尔值为false时返回的Visibility, Hidden表示隐藏可锚定项。

完整的答案

如果我们看一下LayoutContent.Close(),它被标记为注释:

请注意,锚定通常只是隐藏(不关闭)。默认情况下,当用户单击X按钮时,它只隐藏内容。

所以这个不应该被调用。看看堆栈跟踪,这是从:

// LayoutItem class.
protected virtual void OnVisibilityChanged()
{
    if (LayoutElement != null &&
        Visibility == System.Windows.Visibility.Collapsed)
        LayoutElement.Close();
}

根据微软的说法,System.Windows.Visibility.Collapsed意味着该项目是不可见的,并且在布局期间不为它保留空间。这听起来就像当我们点击X隐藏锚点时发生的事情(这可能发生在视觉树的某个地方)。但是为什么评论说这通常不被称为主播呢?如果我们看LayoutAnchorableItem.OnVisibilityChanged():

protected override void OnVisibilityChanged()
{
    if (_anchorable != null && _anchorable.Root != null)
    {
        if (_visibilityReentrantFlag.CanEnter)
        {
            using (_visibilityReentrantFlag.Enter())
            {
                if (Visibility == System.Windows.Visibility.Hidden)
                    _anchorable.Hide(false);
                else if (Visibility == System.Windows.Visibility.Visible)
                    _anchorable.Show();
            }
        }
    }
    base.OnVisibilityChanged();
}

很明显,AvalonDock使用Visibility.Hidden值来表示可锚定是隐藏的。(这对我来说有点困惑,因为微软说Hidden隐藏了元素,但在布局中保留了空间,这不是当你隐藏它时锚定的行为。)那么为什么可见度是Collapsed而不是Hidden呢?答案就在BoolToVisibilityConverter中。

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    if (value is bool && targetType == typeof(Visibility))
    {
        bool val = (bool)value;
        if (val)
            return Visibility.Visible;
        else
            if (parameter != null && parameter is Visibility)
                return parameter;
            else
                return Visibility.Collapsed;
    }
    // ...
}

除非传递Visibility类型的参数,否则当布尔值为false时使用Visibility.Collapsed。我们想让false表示Visibility.Hidden所以我们把它设置为ConverterParameter

<Setter Property="Visibility" Value="{Binding Model.IsVisible, ConverterParameter={x:Static Visibility.Hidden}, Converter={StaticResource btvc}, Mode=TwoWay}"/>
相关文章:
  • 没有找到相关文章