wpf - GridSplitter 移动后使用 Expander 调整网格大小不起作用
问题描述
背景
我正在尝试创建一个控件,顶部有一个文件资源管理器,TreeView
底部由GridSplitter
. 用户可以更改文件资源管理器的大小,但不能超过最小值。当它Expander
被折叠时,它TreeView
会占据所有房间。展开Expander
后,它会恢复到折叠前的大小。
例子
使用这篇文章,我尝试制作一个工作示例。
<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,0,3,0"/>
<Border Grid.Row="2" BorderBrush="Green" BorderThickness="3"/>
</Grid>
当我折叠和展开GridSplitter
.
问题 1
问题 2
我可以调整超出MinHeight
我放在行中的 150 的RowDefinition
大小Expander
。
如何解决这些问题?
解决方案
您当前的 XAML 不起作用有几个原因。
- 您的 MinHeight 设置在嵌套在 GridSplitter 看不到的面板内的元素上。所以它永远不会尊重大小。
- GridSplitter 会覆盖其相邻 RowDefinitions 的 Height 属性,因此,您不能使用样式触发器来操纵高度,以便在 Expander 展开和折叠时动态调整大小
- 当 Expander 折叠并再次展开时,没有简单的方法可以恢复 RowDefinition 之前的 Height。
这是一个工作示例,我在其中重组了您的 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,0,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),
typeof(ExpanderRowHeightBehavior),
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),
typeof(ExpanderRowHeightBehavior),
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;
}
}
}
推荐阅读
- python - 无法解析功能:来自无效参数的 goog:chromeOptions:无法识别的 chrome 选项:首选项
- node.js - TypeError:GraphQLObjectType 不是构造函数
- mysql - 需要以 2020 年 1 月、2019 年 2 月、... 的格式显示数据,使用 SQL
- python - 拒绝 latin1_swedish_ci 以外的所有排序规则
- clearcase - 用户无法在我们的两台 ClearCase 服务器上工作
- shiny - 数据表中行回调中的边框样式
- python - sqlite3 表 Python 字符串格式化程序参数的变量值
- c - 如何使用 qsort() 根据它们与其他参考点的斜率对点进行排序?(没有 qsort_r()/qsort_s())
- python - 从文件中读取时如何在for循环中找到它的最后一项 - Python
- c - 使用 C 合并链表