Skip to content

Instantly share code, notes, and snippets.

@brinko99
Last active September 14, 2022 06:12
Show Gist options
  • Save brinko99/5e7121740b7042604ad47d98750e2961 to your computer and use it in GitHub Desktop.
Save brinko99/5e7121740b7042604ad47d98750e2961 to your computer and use it in GitHub Desktop.
WPF CollapsibleRowDefinition, CollapsibleColumnDefinition
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace Controls
{
/// <summary>
/// <see cref="RowDefinition"/> implementation that supports a collapsed state.
/// </summary>
/// <remarks>
/// A <c>RowDefinition</c>, when used with a <see cref="GridSplitter"/>, can produce undesired behavior if the row needs to be
/// collapsible. That is, the row needs to support a collapsed state, possibly to be invisible or with a minimum height. This class
/// can be used for this purpose with separate heights specified for both the collapsed and expanded states.
/// </remarks>
/// <example>
/// <code><![CDATA[
/// <Grid.RowDefinitions>
/// <controls:CollapsibleRowDefinition CollapsedHeight="0" ExpandedHeight="500" IsExpanded="{Binding HeaderVisible}"/>
/// <RowDefinition Height="Auto"/>
/// <RowDefinition Height="*"/>
/// </Grid.RowDefinitions>
/// ]]></code>
/// </example>
/// <seealso cref="System.Windows.Controls.RowDefinition" />
/// <seealso cref="CollapsibleColumnDefinition"/>
public class CollapsibleRowDefinition : RowDefinition
{
// NOTE: Inspired by https://stackoverflow.com/a/33640443/84522
/// <summary>
/// The property that indicates whether the row is expanded
/// </summary>
public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register(
"IsExpanded",
typeof(bool),
typeof(CollapsibleRowDefinition),
new FrameworkPropertyMetadata(
false,
(s, e) => { ((CollapsibleRowDefinition)s).IsExpanded = (bool)e.NewValue; }));
private bool _isExpanded;
/// <summary>
/// Initializes a new instance of the <see cref="CollapsibleRowDefinition"/> class.
/// </summary>
public CollapsibleRowDefinition()
{
DependencyPropertyDescriptor.FromProperty(
HeightProperty,
typeof(RowDefinition)).AddValueChanged(
this,
(sender, args) =>
{
if (IsExpanded)
{
ExpandedHeight = Height;
}
});
}
/// <summary>
/// Gets or sets the collapsed height of the row.
/// </summary>
public GridLength CollapsedHeight { get; set; }
/// <summary>
/// Gets or sets the expanded height of the row.
/// </summary>
public GridLength ExpandedHeight { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the row is expanded
/// </summary>
public bool IsExpanded
{
get => _isExpanded;
set
{
if (_isExpanded == value)
{
return;
}
_isExpanded = value;
Height = _isExpanded ? ExpandedHeight : CollapsedWidth;
}
}
}
/// <summary>
/// <see cref="ColumnDefinition"/> implementation that supports a collapsed state.
/// </summary>
/// <remarks>
/// A <c>ColumnDefinition</c>, when used with a <see cref="GridSplitter"/>, can produce undesired behavior if the column needs to be
/// collapsible. That is, the column needs to support a collapsed state, possibly to be invisible or with a minimum width. This class
/// can be used for this purpose with separate widths specified for both the collapsed and expanded states.
/// </remarks>
/// <example>
/// <code><![CDATA[
/// <Grid.ColumnDefinitions>
/// <controls:CollapsibleColumnDefinition CollapsedWidth="0" ExpandedWidth="500" IsExpanded="{Binding HeaderVisible}"/>
/// <ColumnDefinition Width="Auto"/>
/// <ColumnDefinition Width="*"/>
/// </Grid.ColumnDefinitions>
/// ]]></code>
/// </example>
/// <seealso cref="System.Windows.Controls.ColumnDefinition" />
/// <seealso cref="CollapsibleRowDefinition"/>
public class CollapsibleColumnDefinition : ColumnDefinition
{
// NOTE: Inspired by https://stackoverflow.com/a/33640443/84522
/// <summary>
/// The property that indicates whether the column is expanded
/// </summary>
public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register(
"IsExpanded",
typeof(bool),
typeof(CollapsibleColumnDefinition),
new FrameworkPropertyMetadata(
false,
(s, e) => { ((CollapsibleColumnDefinition)s).IsExpanded = (bool)e.NewValue; }));
private bool _isExpanded;
/// <summary>
/// Initializes a new instance of the <see cref="CollapsibleColumnDefinition"/> class.
/// </summary>
public CollapsibleColumnDefinition()
{
DependencyPropertyDescriptor.FromProperty(
WidthProperty,
typeof(ColumnDefinition)).AddValueChanged(
this,
(sender, args) =>
{
if (IsExpanded)
{
ExpandedWidth = Width;
}
});
}
/// <summary>
/// Gets or sets the collapsed width of the column.
/// </summary>
public GridLength CollapsedWidth { get; set; }
/// <summary>
/// Gets or sets the expanded width of the column.
/// </summary>
public GridLength ExpandedWidth { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the column is expanded
/// </summary>
public bool IsExpanded
{
get => _isExpanded;
set
{
if (_isExpanded == value)
{
return;
}
_isExpanded = value;
Width = _isExpanded ? ExpandedWidth : CollapsedWidth;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment