GridSplitter移动后,无法使用Expander调整网格大小

问题描述

背景

我正在尝试创建一个控件,该控件的顶部是文件浏览器,而在底部python2 -c 'import rpm' /usr/local/lib/python2.7/dist-packages/rpm.py:15: UserWarning: The RPM Python bindings are not currently available via PyPI. Please install them with your distro package manager (typically called 'python2-rpm' or 'python3-rpm'),and ensure that any virtual environments needing the API are configured to be able to see the system site packages directory. warnings.warn(warning_msg) 的{​​{1}}。用户可以更改文件浏览器的大小,但不能超过最小值。 TreeView折叠后,GridSplitter占据了所有空间。展开Expander后,它会恢复到折叠前的大小。

Background

示例

我使用this帖子试图举一个可行的例子。

TreeView

当我折叠并展开Expander时,调整大小首先起作用。

Example

问题1

移动<Grid Margin="3"> <Grid.RowDeFinitions> <RowDeFinition Height="Auto"/> <RowDeFinition Height="Auto" /> <RowDeFinition Height="3*" /> </Grid.RowDeFinitions> <Border BorderBrush="Red" BorderThickness="3"> <Grid Grid.Row="0"> <Grid.RowDeFinitions> <RowDeFinition Height="Auto"/> <RowDeFinition> <RowDeFinition.Style> <Style targettype="{x:Type RowDeFinition}"> <Setter Property="Height" Value="*" /> <Setter Property="MinHeight" Value="150" /> <Style.Triggers> <DataTrigger Binding="{Binding ElementName=MyExpander,Path=IsExpanded}" Value="False"> <Setter Property="Height" Value="24" /> <Setter Property="MinHeight" Value="24" /> </DataTrigger> </Style.Triggers> </Style> </RowDeFinition.Style> </RowDeFinition> </Grid.RowDeFinitions> <Button Grid.Row="0" Margin="3" Content="Button 1" HorizontalAlignment="Stretch"/> <Expander x:Name="MyExpander" Grid.Row="1" Margin="3" IsExpanded="True"> <Border BorderBrush="Blue" BorderThickness="3"/> </Expander> </Grid> </Border> <GridSplitter Grid.Row="1" Height="3" HorizontalAlignment="Stretch" Margin="3,3,0"/> <Border Grid.Row="2" BorderBrush="Green" BorderThickness="3"/> </Grid> 后,折叠后的大小调整将不再起作用。

Problem 1

问题2

我可以调整大小,使其超过GridSplitter行的GridSplitter中放置的150中的MinHeight

Problem 2

如何解决这些问题?

解决方法

当前XAML不起作用的原因有两个。

  1. 您的MinHeight设置在GridSplitter看不到的面板内嵌套的元素上。因此,它将永远无法兑现尺寸。
  2. GridSplitter会覆盖其相邻的RowDefinitions的Height属性,因此,您无法使用样式触发器来控制Height以便在Expander展开和折叠时动态调整大小
  3. 当Expander折叠并再次展开时,没有简单的方法来恢复RowDefinition的先前高度。

这是一个有效的示例,在此示例中,我已对XAML进行了重组,以便GridSplitter可以遵循Expander的MinHeight。

我还介绍了一个简单的附加行为类,该类将对Expander的Expanded和Collapsed事件作出反应,并将适当的目标RowDefinition的Height设置为Auto,以便获得所需的自动调整大小。

附加的行为类还将保留目标RowDefinition的先前高度,并在扩展器展开时将其还原。

XAML

<Grid Margin="3">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition x:Name="ExpanderRow">
            <RowDefinition.Style>
                <Style TargetType="{x:Type RowDefinition}">
                    <Setter Property="MinHeight" Value="150" />
                    <Style.Triggers>
                        <DataTrigger
                            Binding="{Binding ElementName=MyExpander,Path=IsExpanded}"
                            Value="False">
                            <Setter Property="MinHeight" Value="40" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </RowDefinition.Style>
        </RowDefinition>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Border
        Grid.Row="0"
        Grid.RowSpan="2"
        BorderBrush="Red"
        BorderThickness="3" />

    <Button
        Grid.Row="0"
        Margin="6"
        HorizontalAlignment="Stretch"
        Content="Button 1" />

    <Expander x:Name="MyExpander"
        Grid.Row="1"
        Margin="6"
        local:ExpanderRowHeightBehavior.IsEnabled="True"
        local:ExpanderRowHeightBehavior.TargetRow="{Binding ElementName=ExpanderRow}"
        IsExpanded="True">
        <Border
            BorderBrush="Blue"
            BorderThickness="3" />
    </Expander>

    <GridSplitter
        Grid.Row="2"
        Height="3"
        Margin="3,3,0"
        HorizontalAlignment="Stretch"
        VerticalAlignment="Center" />

    <Border
        Grid.Row="3"
        BorderBrush="Green"
        BorderThickness="3" />
</Grid>

ExpanderRowHeightBehavior.cs

using System.Windows;
using System.Windows.Controls;

namespace SO
{
    public static class ExpanderRowHeightBehavior
    {
        #region IsEnabled (Attached Property)
        public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.RegisterAttached(
                "IsEnabled",typeof(bool),typeof(ExpanderRowHeightBehavior),new PropertyMetadata(false,OnIsEnabledChanged));

        public static bool GetIsEnabled(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsEnabledProperty);
        }

        public static void SetIsEnabled(DependencyObject obj,bool value)
        {
            obj.SetValue(IsEnabledProperty,value);
        }

        private static void OnIsEnabledChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
        {
            if (!(d is Expander expander)) return;

            expander.Collapsed += OnCollapsed;
            expander.Expanded += OnExpanded;

        }
        #endregion

        #region TargetRow (Attached Property)
        public static readonly DependencyProperty TargetRowProperty =
            DependencyProperty.RegisterAttached(
                "TargetRow",typeof(RowDefinition),new PropertyMetadata(null));

        public static RowDefinition GetTargetRow(DependencyObject obj)
        {
            return (RowDefinition)obj.GetValue(TargetRowProperty);
        }

        public static void SetTargetRow(DependencyObject obj,RowDefinition value)
        {
            obj.SetValue(TargetRowProperty,value);
        }
        #endregion

        #region TargetRowPrevHeight (Attached Property)
        public static readonly DependencyProperty TargetRowPrevHeightProperty =
            DependencyProperty.RegisterAttached(
                "TargetRowPrevHeight",typeof(GridLength),new PropertyMetadata(GridLength.Auto));

        public static GridLength GetTargetRowPrevHeight(DependencyObject obj)
        {
            return (GridLength)obj.GetValue(TargetRowPrevHeightProperty);
        }

        public static void SetTargetRowPrevHeight(DependencyObject obj,GridLength value)
        {
            obj.SetValue(TargetRowPrevHeightProperty,value);
        }
        #endregion

        private static void OnCollapsed(object sender,RoutedEventArgs e)
        {
            if (!(sender is Expander expander)) return;

            var targetRow = GetTargetRow(expander);

            if (targetRow == null) return;

            SetTargetRowPrevHeight(expander,targetRow.Height);

            targetRow.Height = GridLength.Auto;
        }

        private static void OnExpanded(object sender,RoutedEventArgs e)
        {
            if (!(sender is Expander expander)) return;

            var targetRow = GetTargetRow(expander);

            if (targetRow == null) return;

            var targetRowPrevHeight = GetTargetRowPrevHeight(expander);

            targetRow.Height = targetRowPrevHeight;
        }
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...