Collapse Grid Row in WPF

I have created a custom WPF element extended from RowDefinition that should collapse rows in a grid when the Collapsed property of the element is set to True.

It does it by using a converter and a datatrigger in a style to set the height of the row to 0. It is based on this SO Answer.

In the example below, this works perfectly when the grid splitter is over half way up the window. However, when it is less than half way, the rows still collapse, but the first row does not expand. Instead, there is just a white gap where the rows used to be. This can be seen in the image below.

Picture shows under half, the bottom row doesn't disappear, but over half it does

Similarly, if MinHeight or MaxHeight is set on any of the rows that are collapsed, it no longer collapses the row at all. I tried to fix this by adding setters for these properties in the data trigger but it did not fix it.

My question is what can be done differently so that it does not matter about the size of the rows or if MinHeight / MaxHeight are set, it is just able to collapse the rows?

MainWindow.xaml.cs

using System;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace RowCollapsibleMCVE
{
    public partial class MainWindow : INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private bool isCollapsed;

        public bool IsCollapsed
        {
            get => isCollapsed;
            set
            {
                isCollapsed = value;
                OnPropertyChanged();
            }
        }
    }

    public class CollapsibleRow : RowDefinition
    {
        #region Default Values
        private const bool COLLAPSED_DEFAULT = false;
        private const bool INVERT_COLLAPSED_DEFAULT = false;
        #endregion

        #region Dependency Properties
        public static readonly DependencyProperty CollapsedProperty =
            DependencyProperty.Register("Collapsed", typeof(bool), typeof(CollapsibleRow), new PropertyMetadata(COLLAPSED_DEFAULT));

        public static readonly DependencyProperty InvertCollapsedProperty =
            DependencyProperty.Register("InvertCollapsed", typeof(bool), typeof(CollapsibleRow), new PropertyMetadata(INVERT_COLLAPSED_DEFAULT));
        #endregion

        #region Properties
        public bool Collapsed {
            get => (bool)GetValue(CollapsedProperty);
            set => SetValue(CollapsedProperty, value);
        }

        public bool InvertCollapsed {
            get => (bool)GetValue(InvertCollapsedProperty);
            set => SetValue(InvertCollapsedProperty, value);
        }
        #endregion
    }

    public class BoolVisibilityConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values.Length > 0 && values[0] is bool collapsed)
            {
                if (values.Length > 1 && values[1] is bool invert && invert)
                {
                    collapsed = !collapsed;
                }

                return collapsed ? Visibility.Collapsed : Visibility.Visible;
            }

            return Visibility.Collapsed;
        }

        public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}
MainWindow.xaml

<Window x:Class="RowCollapsibleMCVE.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:RowCollapsibleMCVE"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Visibility x:Key="CollapsedVisibilityVal">Collapsed</Visibility>
        <local:BoolVisibilityConverter x:Key="BoolVisibilityConverter"/>

        <Style TargetType="{x:Type local:CollapsibleRow}">
            <Style.Triggers>
                <DataTrigger Value="{StaticResource CollapsedVisibilityVal}">
                    <DataTrigger.Binding>
                        <MultiBinding Converter="{StaticResource BoolVisibilityConverter}">
                            <Binding Path="Collapsed"
                                     RelativeSource="{RelativeSource Self}"/>
                            <Binding Path="InvertCollapsed"
                                     RelativeSource="{RelativeSource Self}"/>
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <DataTrigger.Setters>
                        <Setter Property="MinHeight" Value="0"/>
                        <Setter Property="Height" Value="0"/>
                        <Setter Property="MaxHeight" Value="0"/>
                    </DataTrigger.Setters>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <CheckBox Content="Collapse Row"
                  IsChecked="{Binding IsCollapsed}"/>
        <Grid Row="1">
            <Grid.RowDefinitions>
                <local:CollapsibleRow Height="3*" />
                <local:CollapsibleRow Collapsed="{Binding IsCollapsed}" Height="Auto" />
                <local:CollapsibleRow Collapsed="{Binding IsCollapsed}" Height="*" />
            </Grid.RowDefinitions>
            <StackPanel Background="Red"/>

            <GridSplitter Grid.Row="1"
                          Height="10"
                          HorizontalAlignment="Stretch"/>

            <StackPanel Background="Blue"
                        Grid.Row="2"/>
        </Grid>
    </Grid>
</Window>

转载地址

猜你喜欢

转载自blog.csdn.net/qq_28368039/article/details/85758430
Row