diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml index 741c1e41215..28146f668d4 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml @@ -11,34 +11,44 @@ + Header="This is the header - expander 1" + HorizontalContentAlignment="Stretch" + Foreground="White" + Background="{Binding Path=BackgroundExpander1.Value, Mode=TwoWay}" + IsExpanded="{Binding Path=IsExpanded1.Value, Mode=TwoWay}" + ExpandDirection="{Binding Path=ExpandDirection1.Value, Mode=TwoWay}" + DisplayMode="{Binding Path=DisplayMode1.Value, Mode=TwoWay}"> + TextWrapping="Wrap" + Text="This is the content" + VerticalAlignment="Center" + Style="{StaticResource HeaderTextBlockStyle}" /> + + + + + + + Header="This is the header - expander 2" + HorizontalContentAlignment="Stretch" + Foreground="White" + Background="{Binding Path=BackgroundExpander2.Value, Mode=TwoWay}" + IsExpanded="{Binding Path=IsExpanded2.Value, Mode=TwoWay}" + ExpandDirection="{Binding Path=ExpandDirection2.Value, Mode=TwoWay}" + DisplayMode="{Binding Path=DisplayMode2.Value, Mode=TwoWay}"> + TextWrapping="Wrap" + Text="This is the content" + VerticalAlignment="Center" + Style="{StaticResource HeaderTextBlockStyle}" /> diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderXaml.bind index b965f9c5703..30f10fcead0 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderXaml.bind +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderXaml.bind @@ -9,33 +9,45 @@ - + + TextWrapping="Wrap" + Text="This is the content" + VerticalAlignment="Center" + Style="{StaticResource HeaderTextBlockStyle}" /> + + + + + + - + + TextWrapping="Wrap" + Text="This is the content" + VerticalAlignment="Center" + Style="{StaticResource HeaderTextBlockStyle}" /> diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.Constants.cs b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.Constants.cs index 1a85908638f..97f146c4fde 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.Constants.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.Constants.cs @@ -18,19 +18,69 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls public partial class Expander { /// - /// Key of the VisualStateGroup that open/close content + /// Key of the VisualStateGroup that trigger display mode (visible/collapsed/overlay) and direction content /// - private const string ExpandedGroupStateContent = "ExpandedStates"; + private const string DisplayModeAndDirectionStatesGroupStateContent = "DisplayModeAndDirectionStates"; /// - /// Key of the VisualState when content is expanded + /// Key of the VisualState when expander is visible and expander direction is set to Left /// - private const string StateContentExpanded = "Expanded"; + private const string StateContentVisibleLeft = "VisibleLeft"; /// - /// Key of the VisualState when content is collapsed + /// Key of the VisualState when expander is visible and expander direction is set to Down /// - private const string StateContentCollapsed = "Collapsed"; + private const string StateContentVisibleDown = "VisibleDown"; + + /// + /// Key of the VisualState when expander is visible and expander direction is set to Right + /// + private const string StateContentVisibleRight = "VisibleRight"; + + /// + /// Key of the VisualState when expander is visible and expander direction is set to Up + /// + private const string StateContentVisibleUp = "VisibleUp"; + + /// + /// Key of the VisualState when expander is collapsed and expander direction is set to Left + /// + private const string StateContentCollapsedLeft = "CollapsedLeft"; + + /// + /// Key of the VisualState when expander is collapsed and expander direction is set to Down + /// + private const string StateContentCollapsedDown = "CollapsedDown"; + + /// + /// Key of the VisualState when expander is collapsed and expander direction is set to Right + /// + private const string StateContentCollapsedRight = "CollapsedRight"; + + /// + /// Key of the VisualState when expander is collapsed and expander direction is set to Up + /// + private const string StateContentCollapsedUp = "CollapsedUp"; + + /// + /// Key of the VisualState when expander is overlay and expander direction is set to Left + /// + private const string StateContentOverlayLeft = "OverlayLeft"; + + /// + /// Key of the VisualState when expander is overlay and expander direction is set to Down + /// + private const string StateContentOverlayDown = "OverlayDown"; + + /// + /// Key of the VisualState when expander is overlay and expander direction is set to Right + /// + private const string StateContentOverlayRight = "OverlayRight"; + + /// + /// Key of the VisualState when expander is overlay and expander direction is set to Up + /// + private const string StateContentOverlayUp = "OverlayUp"; /// /// Key of the UI Element that toggle IsExpanded property @@ -76,5 +126,10 @@ public partial class Expander /// Key of the UI Element that contains the content of the LayoutTransformer (of the expander button) /// private const string LayoutTransformerPart = "PART_LayoutTransformer"; + + /// + /// Key of the UI Element that contains the content of the control that is visible in Overlay mode + /// + private const string ContentOverlayPart = "PART_ContentOverlay"; } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.Properties.cs b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.Properties.cs index a43e558128a..f31b3d6b8fa 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.Properties.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.Properties.cs @@ -43,6 +43,18 @@ public partial class Expander public static readonly DependencyProperty ExpandDirectionProperty = DependencyProperty.Register(nameof(ExpandDirection), typeof(ExpandDirection), typeof(Expander), new PropertyMetadata(ExpandDirection.Down, OnExpandDirectionChanged)); + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty DisplayModeProperty = + DependencyProperty.Register(nameof(DisplayMode), typeof(ExpanderDisplayMode), typeof(Expander), new PropertyMetadata(ExpanderDisplayMode.Expand, OnDisplayModeChanged)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty ContentOverlayProperty = + DependencyProperty.Register(nameof(ContentOverlay), typeof(UIElement), typeof(Expander), new PropertyMetadata(default(UIElement))); + /// /// Gets or sets a value indicating whether the Header of the control. /// @@ -79,6 +91,24 @@ public ExpandDirection ExpandDirection set { SetValue(ExpandDirectionProperty, value); } } + /// + /// Gets or sets a value indicating whether the Expander control should be in Expand or Overlay mode. + /// + public ExpanderDisplayMode DisplayMode + { + get { return (ExpanderDisplayMode)GetValue(DisplayModeProperty); } + set { SetValue(DisplayModeProperty, value); } + } + + /// + /// Gets or sets a value indicating whether the ContentOverlay of the control. + /// + public UIElement ContentOverlay + { + get { return (UIElement)GetValue(ContentOverlayProperty); } + set { SetValue(ContentOverlayProperty, value); } + } + private static void OnIsExpandedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var expander = d as Expander; @@ -105,5 +135,17 @@ private static void OnExpandDirectionChanged(DependencyObject d, DependencyPrope expander.OnExpandDirectionChanged(); } } + + private static void OnDisplayModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var expander = d as Expander; + var previousDisplayMode = (ExpanderDisplayMode)e.OldValue; + var newDisplayMode = (ExpanderDisplayMode)e.NewValue; + + if (previousDisplayMode != newDisplayMode) + { + expander.OnDisplayModeOrIsExpandedChanged(); + } + } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.cs b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.cs index c0579d9f4b9..d66f47724b8 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.cs @@ -15,6 +15,7 @@ using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Markup; namespace Microsoft.Toolkit.Uwp.UI.Controls @@ -22,15 +23,26 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls /// /// The control allows user to show/hide content based on a boolean state /// - [TemplateVisualState(Name = StateContentExpanded, GroupName = ExpandedGroupStateContent)] - [TemplateVisualState(Name = StateContentCollapsed, GroupName = ExpandedGroupStateContent)] [TemplateVisualState(Name = StateContentLeftDirection, GroupName = ExpandDirectionGroupStateContent)] [TemplateVisualState(Name = StateContentDownDirection, GroupName = ExpandDirectionGroupStateContent)] [TemplateVisualState(Name = StateContentRightDirection, GroupName = ExpandDirectionGroupStateContent)] [TemplateVisualState(Name = StateContentUpDirection, GroupName = ExpandDirectionGroupStateContent)] + [TemplateVisualState(Name = StateContentVisibleLeft, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentVisibleDown, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentVisibleRight, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentVisibleUp, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentCollapsedLeft, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentCollapsedDown, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentCollapsedRight, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentCollapsedUp, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentOverlayLeft, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentOverlayDown, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentOverlayRight, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] + [TemplateVisualState(Name = StateContentOverlayUp, GroupName = DisplayModeAndDirectionStatesGroupStateContent)] [TemplatePart(Name = RootGridPart, Type = typeof(Grid))] [TemplatePart(Name = ExpanderToggleButtonPart, Type = typeof(ToggleButton))] [TemplatePart(Name = LayoutTransformerPart, Type = typeof(LayoutTransformControl))] + [TemplatePart(Name = ContentOverlayPart, Type = typeof(ContentPresenter))] [ContentProperty(Name = "Content")] public partial class Expander : ContentControl { @@ -47,15 +59,6 @@ protected override void OnApplyTemplate() { base.OnApplyTemplate(); - if (IsExpanded) - { - VisualStateManager.GoToState(this, StateContentExpanded, false); - } - else - { - VisualStateManager.GoToState(this, StateContentCollapsed, false); - } - var button = (ToggleButton)GetTemplateChild(ExpanderToggleButtonPart); if (button != null) @@ -65,6 +68,7 @@ protected override void OnApplyTemplate() } OnExpandDirectionChanged(); + OnDisplayModeOrIsExpandedChanged(false); } /// @@ -85,7 +89,7 @@ protected virtual void OnCollapsed(EventArgs args) Collapsed?.Invoke(this, args); } - private void ExpanderToggleButtonPart_KeyDown(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e) + private void ExpanderToggleButtonPart_KeyDown(object sender, KeyRoutedEventArgs e) { if (e.Key != VirtualKey.Enter) { @@ -106,20 +110,20 @@ private void ExpanderToggleButtonPart_KeyDown(object sender, Windows.UI.Xaml.Inp private void ExpandControl() { - VisualStateManager.GoToState(this, StateContentExpanded, true); + OnDisplayModeOrIsExpandedChanged(); OnExpanded(EventArgs.Empty); } private void CollapseControl() { - VisualStateManager.GoToState(this, StateContentCollapsed, true); + OnDisplayModeOrIsExpandedChanged(); OnCollapsed(EventArgs.Empty); } /// /// Called when the ExpandDirection on Expander changes /// - public void OnExpandDirectionChanged() + private void OnExpandDirectionChanged() { var button = (ToggleButton)GetTemplateChild(ExpanderToggleButtonPart); @@ -128,22 +132,20 @@ public void OnExpandDirectionChanged() return; } + UpdateDisplayModeOrExpanderDirection(); + switch (ExpandDirection) { case ExpandDirection.Left: - VisualStateManager.GoToState(this, StateContentLeftDirection, true); VisualStateManager.GoToState(button, StateContentLeftDirection, true); break; case ExpandDirection.Down: - VisualStateManager.GoToState(this, StateContentDownDirection, true); VisualStateManager.GoToState(button, StateContentDownDirection, true); break; case ExpandDirection.Right: - VisualStateManager.GoToState(this, StateContentRightDirection, true); VisualStateManager.GoToState(button, StateContentRightDirection, true); break; case ExpandDirection.Up: - VisualStateManager.GoToState(this, StateContentUpDirection, true); VisualStateManager.GoToState(button, StateContentUpDirection, true); break; } @@ -155,5 +157,54 @@ public void OnExpandDirectionChanged() VisualStateManager.GoToState(button, "Checked", true); } } + + private void OnDisplayModeOrIsExpandedChanged(bool useTransitions = true) + { + UpdateDisplayModeOrExpanderDirection(); + } + + private void UpdateDisplayModeOrExpanderDirection() + { + string visualState = null; + + switch (ExpandDirection) + { + case ExpandDirection.Left: + visualState = GetDisplayModeVisualState(StateContentOverlayLeft, StateContentCollapsedLeft, StateContentVisibleLeft); + break; + case ExpandDirection.Down: + visualState = GetDisplayModeVisualState(StateContentOverlayDown, StateContentCollapsedDown, StateContentVisibleDown); + break; + case ExpandDirection.Right: + visualState = GetDisplayModeVisualState(StateContentOverlayRight, StateContentCollapsedRight, StateContentVisibleRight); + break; + case ExpandDirection.Up: + visualState = GetDisplayModeVisualState(StateContentOverlayUp, StateContentCollapsedUp, StateContentVisibleUp); + break; + } + + if (!string.IsNullOrWhiteSpace(visualState)) + { + VisualStateManager.GoToState(this, visualState, true); + } + } + + private string GetDisplayModeVisualState(string overlayState, string collapsedState, string visibleState) + { + if (!IsExpanded && DisplayMode == ExpanderDisplayMode.Overlay) + { + // Overlay + return overlayState; + } + + if (!IsExpanded && DisplayMode == ExpanderDisplayMode.Expand) + { + // Collapsed + return collapsedState; + } + + // Visible + return visibleState; + } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.xaml b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.xaml index 5f357e1150e..47e5c66bde5 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.xaml +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.xaml @@ -325,22 +325,168 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -351,14 +497,42 @@ + + + + + + + + - + + + + - + + + + + + + + + + + + + + + + + + @@ -369,15 +543,91 @@ + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -388,8 +638,24 @@ + + + + + + + + + + + + + + + + @@ -424,13 +690,31 @@ IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" /> + + + + + + + VerticalContentAlignment="Stretch" + Visibility="Collapsed"> + + + + diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/Expander/ExpanderDisplayMode.cs b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/ExpanderDisplayMode.cs new file mode 100644 index 00000000000..0225fb1aa5f --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI.Controls/Expander/ExpanderDisplayMode.cs @@ -0,0 +1,30 @@ +// ****************************************************************** +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. +// ****************************************************************** + +namespace Microsoft.Toolkit.Uwp.UI.Controls +{ + /// + /// Display mode of the Expander that will update the behavior of the content visibility + /// + public enum ExpanderDisplayMode + { + /// + /// Default mode (the content is totally collapsed) + /// + Expand, + + /// + /// Overlay mode (only the overlay content is visible) + /// + Overlay + } +} diff --git a/docs/controls/Expander.md b/docs/controls/Expander.md index bf7b1fd7518..daef1947f05 100644 --- a/docs/controls/Expander.md +++ b/docs/controls/Expander.md @@ -17,6 +17,7 @@ You can use these properties : * HeaderTemplate * IsExpanded (define if the content is visible or not) * ExpandDirection +* DisplayMode You can also use these events : @@ -52,6 +53,13 @@ The `ExpandDirection` property can take 4 values that will expand the content ba * `Right` - from left to right * `Left` - from right to left +### DisplayMode + +The `DisplayMode` property can take 2 values that will modify the behavior of the Expander control: + +* `Expand` - the content is either visible or collapsed (default) +* `Overlay` - when the content is collapsed, an overlay content is shown + ## Example Image ![Expander animation](../resources/images/Controls-Expander.gif "Expander")