如何让设为0像素的Grid子元素(Border)跟随列调整大小?
解决方案:通过GridSplitter的DragStarted事件处理折叠后的拖动问题
问题根源在于左侧面板折叠时,对应列宽被设为0 Pixel,此时GridSplitter无法对宽度为0的列进行调整。我们可以利用GridSplitter的DragStarted事件(拖动开始时触发),自动展开面板并恢复列宽,让拖动操作正常生效。
步骤1:修改XAML,添加GridSplitter的DragStarted事件
给GridSplitter绑定事件:
<GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" DragStarted="GridSplitter_DragStarted"/>
步骤2:后台添加事件处理逻辑
在Repro类中新增事件处理方法:
private void GridSplitter_DragStarted(object sender, DragStartedEventArgs e) { // 若左侧面板处于折叠状态,自动触发展开逻辑 if (PanelVisibility == Visibility.Collapsed) { PanelVisibility = Visibility.Visible; ContainerGrid.ColumnDefinitions[2].Width = _videoPanelWidth; ContainerGrid.ColumnDefinitions[0].Width = _propPanelWidth; } }
补充说明
- 选择
DragStarted的原因:它在拖动动作启动瞬间触发,能在用户开始调整前就恢复面板状态,保证拖动体验连贯。DragDelta会在拖动过程中才触发,存在延迟感;Mouse系列事件则需要额外处理更多状态判断,不如DragStarted直接高效。 - 原有手动折叠/展开逻辑无需改动,仅在拖动开始时自动触发展开,不影响按钮的手动控制功能。
修改后的完整代码
XAML部分
<UserControl x:Class="SublimeTriptych.control.Repro" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:SublimeTriptych.control" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid Name="ContainerGrid"> <Grid.ColumnDefinitions> <ColumnDefinition Width="160"/> <ColumnDefinition Width="4"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Border Grid.ColumnSpan="1" Background="Gold" Visibility="{Binding PanelVisibility, Mode=OneWay, RelativeSource={RelativeSource AncestorType=local:Repro}}"/> <GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" DragStarted="GridSplitter_DragStarted"/> <Border Grid.Column="2" Background="Orange"/> <DockPanel Grid.ColumnSpan="3" Grid.Column="0" VerticalAlignment="Bottom"> <Button HorizontalAlignment="Center" Command="{Binding SwitchVisibilityCommand, RelativeSource={RelativeSource AncestorType=local:Repro}}">👁</Button> </DockPanel> </Grid> </UserControl>
后台代码部分
public partial class Repro : INotifyPropertyChanged { private ICommand? _switchVisibilityCommand; private Visibility _panelVisibility = Visibility.Visible; private GridLength _videoPanelWidth; private GridLength _propPanelWidth; public Repro() { InitializeComponent(); } public ICommand SwitchVisibilityCommand => _switchVisibilityCommand ?? (_switchVisibilityCommand = new DelegateCommandListen( s => { PanelVisibility = PanelVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible; if (PanelVisibility == Visibility.Collapsed) { _propPanelWidth = ContainerGrid.ColumnDefinitions[0].Width; _videoPanelWidth = ContainerGrid.ColumnDefinitions[2].Width; ContainerGrid.ColumnDefinitions[0].Width = new GridLength(0, GridUnitType.Pixel); ContainerGrid.ColumnDefinitions[2].Width = new GridLength(1, GridUnitType.Star); } else { ContainerGrid.ColumnDefinitions[2].Width = _videoPanelWidth; ContainerGrid.ColumnDefinitions[0].Width = _propPanelWidth; } }, s => true)); public Visibility PanelVisibility { get => _panelVisibility; set => SetField(ref _panelVisibility, value); } private void GridSplitter_DragStarted(object sender, DragStartedEventArgs e) { if (PanelVisibility == Visibility.Collapsed) { PanelVisibility = Visibility.Visible; ContainerGrid.ColumnDefinitions[2].Width = _videoPanelWidth; ContainerGrid.ColumnDefinitions[0].Width = _propPanelWidth; } } #region inpc public event PropertyChangedEventHandler? PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } #endregion }
内容的提问来源于stack exchange,提问作者Soleil
相关产品推荐
相关产品推荐

