问题描述
背景
我正在尝试创建一个控件,该控件的顶部是文件浏览器,而在底部是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
后,它会恢复到折叠前的大小。
示例
TreeView
当我折叠并展开Expander
时,调整大小首先起作用。
问题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>
后,折叠后的大小调整将不再起作用。
问题2
我可以调整大小,使其超过GridSplitter
行的GridSplitter
中放置的150中的MinHeight
。
如何解决这些问题?
解决方法
当前XAML不起作用的原因有两个。
- 您的MinHeight设置在GridSplitter看不到的面板内嵌套的元素上。因此,它将永远无法兑现尺寸。
- GridSplitter会覆盖其相邻的RowDefinitions的Height属性,因此,您无法使用样式触发器来控制Height以便在Expander展开和折叠时动态调整大小
- 当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;
}
}
}