【问题标题】:Binding to LayoutAnchorableItem Visibility in AvalonDock 2在 AvalonDock 2 中绑定到 LayoutAnchorableItem 可见性
【发布时间】:2014-06-30 07:51:54
【问题描述】:

我正在尝试将 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)
...

注释掉与可见性的绑定后,anchorable 会按预期隐藏。

【问题讨论】:

    标签: c# wpf avalondock


    【解决方案1】:

    tl;博士

    您需要在 Binding 中添加一个值为 Visibility.HiddenConverterParameter

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

    转换器参数为Visibility,当布尔值为false时返回,Hidden表示anchable被隐藏。

    完整答案

    如果我们看LayoutContent.Close(),它是用评论标记的:

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

    所以这不应该被调用。查看堆栈跟踪,这是从以下位置调用的:

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

    根据微软的说法,System.Windows.Visibility.Collapsed 表示该项目不可见,并且在布局期间没有为其保留空间。这听起来像是当我们单击X 隐藏它们时锚定对象正在发生的事情(这可能发生在视觉树的某个地方)。但是为什么 cmets 说这通常不需要锚定对象呢?如果我们看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 值来指示anchorable 是隐藏的。 (这让我有点困惑,因为 Microsoft 声明 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}"/>
    

    【讨论】:

    • 我之前没有注意到我的问题的后续行动。谢谢你收拾东西?这意味着我可以重新使用主仓库中的源代码。 (对于其他人,这是我的相关问题:stackoverflow.com/questions/21692918/…
    • 谢谢!谢谢!谢谢!谢谢!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 2013-12-13
    • 2022-01-17
    • 2014-08-20
    • 2014-06-17
    • 2017-12-10
    相关资源
    最近更新 更多