wpf切换可见性折叠只工作一次

gwo2fgha  于 2022-12-05  发布在  其他
关注(0)|答案(2)|浏览(144)

我想做的是根据复选框切换来折叠WPF UI的底部部分。到目前为止,这基本上和预期的一样。下面的图像,当你一步一步地浏览时,你会看到一旦网格分割器被移动,折叠就停止工作了。我不明白为什么或者如何修复这个问题。
启动应用程序,显示正确。

切换复选框,底部部分将按预期消失。

再次切换复选框,然后垂直移动拆分器,所有内容都会按预期显示。

现在最后一次切换复选框,你会注意到顶部的部分并没有像以前那样充满应用程序。这是它出现中断的地方!我希望黄色部分像最初切换时那样充满UI。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="525"
        WindowStartupLocation="CenterScreen">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <CheckBox Name="ToggleVisibility" Margin="10" IsChecked="True" Content="Toggle Bottom Section"></CheckBox>

        <StackPanel Background="#feca00" Grid.Row="1">
            <TextBlock FontSize="20" Foreground="#58290A">Top Section</TextBlock>
        </StackPanel>

        <GridSplitter Grid.Row="2" Height="5" HorizontalAlignment="Stretch">
            <GridSplitter.Style>
                <Style TargetType="GridSplitter">
                    <Setter Property="Visibility" Value="Visible" />
                    <Setter Property="Background" Value="Red" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ElementName=ToggleVisibility, Path=IsChecked}" Value="False">
                            <Setter Property="Visibility" Value="Collapsed"></Setter>
                            <Setter Property="Background" Value="Red"></Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </GridSplitter.Style>
        </GridSplitter>

        <StackPanel Grid.Row="3" Background="LightBlue">
            <StackPanel.Style>
                <Style TargetType="StackPanel">
                    <Setter Property="Visibility" Value="Visible" />
                    <Setter Property="Background" Value="Red" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ElementName=ToggleVisibility, Path=IsChecked}" Value="False">
                            <Setter Property="Visibility" Value="Collapsed"></Setter>
                            <Setter Property="Background" Value="Red"></Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </StackPanel.Style>

            <TextBlock FontSize="20" Foreground="black">Bottom Section</TextBlock>
        </StackPanel>

    </Grid>
</Window>
g52tjvyc

g52tjvyc1#

发生这种情况的原因是,当您移动拆分器时,它会覆盖最后一个RowDefinitionHeight属性,并将其设置为Grid(第二个StackPanel)的相应行中显示的任何内容的实际高度(底部区域)。它不再设置为Auto,因此即使折叠底部区域,行仍保持其高度-因此会出现空白区域。
我有时也会遇到类似的情况,我所做的就是使用Grid.RowSpan附加属性将控件(我希望它占据所有空间)跨越其余行。在您的情况下,可以通过将以下样式应用于第一个StackPanel(顶部)来实现:

<Style TargetType="{x:Type StackPanel}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsChecked, ElementName=ToggleVisibility}" Value="False">
            <Setter Property="Grid.RowSpan" Value="3" />
        </DataTrigger>
    </Style.Triggers>
</Style>

然后,StackPanel将跨越到Grid的底部,而不考虑后续行的高度。

编辑

由于您对跨越控件不满意,下面是另一个解决方案:从RowDefinition类派生并连接您自己的可见性逻辑。

public class MyRowDefinition : RowDefinition
{
    static MyRowDefinition()
    {
        HeightProperty.OverrideMetadata(
            typeof(MyRowDefinition),
            new FrameworkPropertyMetadata
            {
                CoerceValueCallback = CoerceHeightPropertyValue
            });
    }

    private static object CoerceHeightPropertyValue(DependencyObject d, object baseValue)
    {
        if (Equals(d.GetValue(IsVisibleProperty), false))
            return new GridLength(0d);
        else
            return baseValue;
    }

    public bool IsVisible
    {
        get { return (bool)GetValue(IsVisibleProperty); }
        set { SetValue(IsVisibleProperty, value); }
    }

    public static readonly DependencyProperty IsVisibleProperty =
        DependencyProperty.Register(
            "IsVisible",
            typeof(bool),
            typeof(MyRowDefinition),
            new FrameworkPropertyMetadata
            {
                DefaultValue = true,
                PropertyChangedCallback = IsVisiblePropertyChanged
            });

    private static void IsVisiblePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        d.InvalidateProperty(RowDefinition.HeightProperty);
    }
}

然后在网格中使用该类而不是RowDefinition,并将IsVisible属性绑定到复选框的选中状态。

xqk2d5yq

xqk2d5yq2#

看起来StackPanelGridSplitter是折叠的,但是Grid.Row 3没有。我不知道为什么自动高度没有关闭它。编辑:我看到@Grx70已经解释过了。
这:Hide grid row in WPF建议将所有子元素设置为Visibility.Collapsed应该可以工作,但是您可以选择将Grid.Row 3的高度设置为0。
我认为你的GridSplitter的Height=“5”可能也会占用空间,优先于样式设置(它被折叠,从那里得到Height 0,但是从Height=“5”那里得到Height 5,它赢了(但是它仍然是不可见的)。在样式中也这样可能更好:

<Setter Property="Height" Value="5" />

相关问题