diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
index 2018763e733..25f6582a0b6 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
@@ -282,6 +282,8 @@
+
+
@@ -329,7 +331,6 @@
-
@@ -399,7 +400,6 @@
-
@@ -647,6 +647,9 @@
+
+
+
@@ -862,9 +865,6 @@
ScrollHeaderPage.xaml
-
- GridSplitterPage.xaml
-
FadeHeaderBehaviorPage.xaml
@@ -1301,10 +1301,6 @@
MSBuild:Compile
Designer
-
- Designer
- MSBuild:Compile
-
MSBuild:Compile
Designer
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Pages/SampleController.xaml b/Microsoft.Toolkit.Uwp.SampleApp/Pages/SampleController.xaml
index 57f54f29aa5..887f76df9cd 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Pages/SampleController.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Pages/SampleController.xaml
@@ -220,8 +220,8 @@
Width="11"
Background="Transparent"
HorizontalAlignment="Left"
- GripperForeground="{ThemeResource Brush-Alt}"
- ParentLevel="1" />
+ ParentLevel="1">
+
+ Foreground="{ThemeResource Brush-Alt}">
@@ -45,16 +44,12 @@
Grid.Row="1"
Background="{ThemeResource Brush-Grey-04}" Height="11"
HorizontalAlignment="Stretch">
-
+ Foreground="{ThemeResource Brush-Alt}" />
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitterPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitterPage.xaml
deleted file mode 100644
index 268de9613bb..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitterPage.xaml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitterPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitterPage.xaml.cs
deleted file mode 100644
index 3afb58d856e..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitterPage.xaml.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Toolkit.Uwp.SampleApp.Models;
-using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Navigation;
-
-namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
-{
- public sealed partial class GridSplitterPage : Page
- {
- public GridSplitterPage()
- {
- InitializeComponent();
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/ContentSizer.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/ContentSizer.bind
new file mode 100644
index 00000000000..2e88e813af1
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/ContentSizer.bind
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Side Content
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/ContentSizer.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/ContentSizer.png
new file mode 100644
index 00000000000..004cf329744
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/ContentSizer.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitter.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/GridSplitter.bind
similarity index 88%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitter.bind
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/GridSplitter.bind
index 4cec3829383..c4d3cc553d8 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitter.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/GridSplitter.bind
@@ -63,12 +63,11 @@
@@ -85,14 +84,6 @@
-
-
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitter.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/GridSplitter.png
similarity index 100%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GridSplitter/GridSplitter.png
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/GridSplitter.png
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/PropertySizer.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/PropertySizer.bind
new file mode 100644
index 00000000000..9f8b66e1661
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Sizers/PropertySizer.bind
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml
index a4187d65e0a..4bb92e0fa4f 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml
@@ -50,6 +50,7 @@
+
@@ -63,6 +64,8 @@
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
index 8cdfcc3a619..aa4eb7f3948 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
@@ -175,16 +175,33 @@
"Icon": "/SamplePages/ScrollHeader/ScrollHeader.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/behaviors/HeaderBehaviors.md"
},
+ {
+ "Name": "ContentSizer",
+ "Subcategory": "Layout",
+ "About": "ContentSizer is a general sizing control which can manipulate the size of its parent or other elements. Used as a building block for more complex UI systems.",
+ "CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/main/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer",
+ "XamlCodeFile": "/SamplePages/Sizers/ContentSizer.bind",
+ "Icon": "/SamplePages/Sizers/ContentSizer.png",
+ "DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/ContentSizer.md"
+ },
{
"Name": "GridSplitter",
- "Type": "GridSplitterPage",
"Subcategory": "Layout",
"About": "GridSplitter represents the control that redistributes space between columns or rows of a Grid control.",
- "CodeUrl": "https://github.com/CommunityToolkit/WindowsCommunityToolkit/tree/main/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter",
- "XamlCodeFile": "GridSplitter.bind",
- "Icon": "/SamplePages/GridSplitter/GridSplitter.png",
+ "CodeUrl": "https://github.com/CommunityToolkit/WindowsCommunityToolkit/tree/main/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter",
+ "XamlCodeFile": "/SamplePages/Sizers/GridSplitter.bind",
+ "Icon": "/SamplePages/Sizers/GridSplitter.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/GridSplitter.md"
},
+ {
+ "Name": "PropertySizer",
+ "Subcategory": "Layout",
+ "About": "PropertySizer is a specific sizing control which can manipulate any double value or some other element or property.",
+ "CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/main/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer",
+ "XamlCodeFile": "/SamplePages/Sizers/PropertySizer.bind",
+ "Icon": "/SamplePages/Sizers/ContentSizer.png",
+ "DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/ContentSizer.md"
+ },
{
"Name": "AttachedDropShadow (Composition)",
"Type": "AttachedDropShadowPage",
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/GridSplitter.Metadata.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/GridSplitter.Metadata.cs
index cfc9fc1fa0e..8a3828601be 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/GridSplitter.Metadata.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/GridSplitter.Metadata.cs
@@ -20,14 +20,12 @@ public GridSplitterMetadata()
b.AddCustomAttributes(nameof(GridSplitter.Element), new CategoryAttribute(Resources.CategoryCommon));
b.AddCustomAttributes(nameof(GridSplitter.ResizeDirection), new CategoryAttribute(Resources.CategoryCommon));
b.AddCustomAttributes(nameof(GridSplitter.ResizeBehavior), new CategoryAttribute(Resources.CategoryCommon));
- b.AddCustomAttributes(nameof(GridSplitter.GripperForeground), new CategoryAttribute(Resources.CategoryBrush));
b.AddCustomAttributes(nameof(GridSplitter.ParentLevel), new CategoryAttribute(Resources.CategoryCommon));
b.AddCustomAttributes(nameof(GridSplitter.GripperCursor), new CategoryAttribute(Resources.CategoryAppearance));
b.AddCustomAttributes(nameof(GridSplitter.GripperCustomCursorResource),
new CategoryAttribute(Resources.CategoryAppearance),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
- b.AddCustomAttributes(nameof(GridSplitter.CursorBehavior), new CategoryAttribute(Resources.CategoryCommon));
b.AddCustomAttributes(new ToolboxCategoryAttribute(ToolboxCategoryPaths.Toolkit, false));
}
);
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/GridSplitter.Typedata.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/GridSplitter.Typedata.cs
index 13c64c02a0e..41bfb550c2f 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/GridSplitter.Typedata.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/GridSplitter.Typedata.cs
@@ -13,11 +13,9 @@ internal static partial class ControlTypes
internal static class GridSplitter
{
- internal const string CursorBehavior = nameof(CursorBehavior);
internal const string Element = nameof(Element);
internal const string GripperCursor = nameof(GripperCursor);
internal const string GripperCustomCursorResource = nameof(GripperCustomCursorResource);
- internal const string GripperForeground = nameof(GripperForeground);
internal const string ParentLevel = nameof(ParentLevel);
internal const string ResizeBehavior = nameof(ResizeBehavior);
internal const string ResizeDirection = nameof(ResizeDirection);
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Data.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Data.cs
deleted file mode 100644
index 6781e4ba1bf..00000000000
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Data.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace Microsoft.Toolkit.Uwp.UI.Controls
-{
- ///
- /// Represents the control that redistributes space between columns or rows of a Grid control.
- ///
- public partial class GridSplitter
- {
- ///
- /// Enum to indicate whether GridSplitter resizes Columns or Rows
- ///
- public enum GridResizeDirection
- {
- ///
- /// Determines whether to resize rows or columns based on its Alignment and
- /// width compared to height
- ///
- Auto,
-
- ///
- /// Resize columns when dragging Splitter.
- ///
- Columns,
-
- ///
- /// Resize rows when dragging Splitter.
- ///
- Rows
- }
-
- ///
- /// Enum to indicate what Columns or Rows the GridSplitter resizes
- ///
- public enum GridResizeBehavior
- {
- ///
- /// Determine which columns or rows to resize based on its Alignment.
- ///
- BasedOnAlignment,
-
- ///
- /// Resize the current and next Columns or Rows.
- ///
- CurrentAndNext,
-
- ///
- /// Resize the previous and current Columns or Rows.
- ///
- PreviousAndCurrent,
-
- ///
- /// Resize the previous and next Columns or Rows.
- ///
- PreviousAndNext
- }
-
- ///
- /// Enum to indicate the supported gripper cursor types.
- ///
- public enum GripperCursorType
- {
- ///
- /// Change the cursor based on the splitter direction
- ///
- Default = -1,
-
- ///
- /// Standard Arrow cursor
- ///
- Arrow,
-
- ///
- /// Standard Cross cursor
- ///
- Cross,
-
- ///
- /// Standard Custom cursor
- ///
- Custom,
-
- ///
- /// Standard Hand cursor
- ///
- Hand,
-
- ///
- /// Standard Help cursor
- ///
- Help,
-
- ///
- /// Standard IBeam cursor
- ///
- IBeam,
-
- ///
- /// Standard SizeAll cursor
- ///
- SizeAll,
-
- ///
- /// Standard SizeNortheastSouthwest cursor
- ///
- SizeNortheastSouthwest,
-
- ///
- /// Standard SizeNorthSouth cursor
- ///
- SizeNorthSouth,
-
- ///
- /// Standard SizeNorthwestSoutheast cursor
- ///
- SizeNorthwestSoutheast,
-
- ///
- /// Standard SizeWestEast cursor
- ///
- SizeWestEast,
-
- ///
- /// Standard UniversalNo cursor
- ///
- UniversalNo,
-
- ///
- /// Standard UpArrow cursor
- ///
- UpArrow,
-
- ///
- /// Standard Wait cursor
- ///
- Wait
- }
-
- ///
- /// Enum to indicate the behavior of window cursor on grid splitter hover
- ///
- public enum SplitterCursorBehavior
- {
- ///
- /// Update window cursor on Grid Splitter hover
- ///
- ChangeOnSplitterHover,
-
- ///
- /// Update window cursor on Grid Splitter Gripper hover
- ///
- ChangeOnGripperHover
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Events.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Events.cs
deleted file mode 100644
index a310d1b7d03..00000000000
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Events.cs
+++ /dev/null
@@ -1,309 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Windows.System;
-using Windows.UI.Core;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Input;
-using Windows.UI.Xaml.Media;
-
-namespace Microsoft.Toolkit.Uwp.UI.Controls
-{
- ///
- /// Represents the control that redistributes space between columns or rows of a Grid control.
- ///
- public partial class GridSplitter
- {
- // Symbols for GripperBar in Segoe MDL2 Assets
- private const string GripperBarVertical = "\xE784";
- private const string GripperBarHorizontal = "\xE76F";
- private const string GripperDisplayFont = "Segoe MDL2 Assets";
-
- private void GridSplitter_Loaded(object sender, RoutedEventArgs e)
- {
- _resizeDirection = GetResizeDirection();
- _resizeBehavior = GetResizeBehavior();
-
- // Adding Grip to Grid Splitter
- if (Element == default(UIElement))
- {
- CreateGripperDisplay();
- Element = _gripperDisplay;
- }
-
- if (_hoverWrapper == null)
- {
- var hoverWrapper = new GripperHoverWrapper(
- CursorBehavior == SplitterCursorBehavior.ChangeOnSplitterHover
- ? this
- : Element,
- _resizeDirection,
- GripperCursor,
- GripperCustomCursorResource);
- ManipulationStarted += hoverWrapper.SplitterManipulationStarted;
- ManipulationCompleted += hoverWrapper.SplitterManipulationCompleted;
-
- _hoverWrapper = hoverWrapper;
- }
- }
-
- private void CreateGripperDisplay()
- {
- if (_gripperDisplay == null)
- {
- _gripperDisplay = new TextBlock
- {
- FontFamily = new FontFamily(GripperDisplayFont),
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- Foreground = GripperForeground,
- Text = _resizeDirection == GridResizeDirection.Columns ? GripperBarVertical : GripperBarHorizontal
- };
- _gripperDisplay.SetValue(
- Windows.UI.Xaml.Automation.AutomationProperties.AccessibilityViewProperty,
- Windows.UI.Xaml.Automation.Peers.AccessibilityView.Raw);
- }
- }
-
- ///
- protected override void OnKeyDown(KeyRoutedEventArgs e)
- {
- var step = 1;
- var ctrl = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control);
- if (ctrl.HasFlag(CoreVirtualKeyStates.Down))
- {
- step = 5;
- }
-
- if (_resizeDirection == GridResizeDirection.Columns)
- {
- if (e.Key == VirtualKey.Left)
- {
- HorizontalMove(-step);
- }
- else if (e.Key == VirtualKey.Right)
- {
- HorizontalMove(step);
- }
- else
- {
- return;
- }
-
- e.Handled = true;
- return;
- }
-
- if (_resizeDirection == GridResizeDirection.Rows)
- {
- if (e.Key == VirtualKey.Up)
- {
- VerticalMove(-step);
- }
- else if (e.Key == VirtualKey.Down)
- {
- VerticalMove(step);
- }
- else
- {
- return;
- }
-
- e.Handled = true;
- }
-
- base.OnKeyDown(e);
- }
-
- ///
- protected override void OnManipulationStarted(ManipulationStartedRoutedEventArgs e)
- {
- // saving the previous state
- PreviousCursor = Window.Current.CoreWindow.PointerCursor;
- _resizeDirection = GetResizeDirection();
- _resizeBehavior = GetResizeBehavior();
-
- if (_resizeDirection == GridResizeDirection.Columns)
- {
- Window.Current.CoreWindow.PointerCursor = ColumnsSplitterCursor;
- }
- else if (_resizeDirection == GridResizeDirection.Rows)
- {
- Window.Current.CoreWindow.PointerCursor = RowSplitterCursor;
- }
-
- base.OnManipulationStarted(e);
- }
-
- ///
- protected override void OnManipulationCompleted(ManipulationCompletedRoutedEventArgs e)
- {
- Window.Current.CoreWindow.PointerCursor = PreviousCursor;
-
- base.OnManipulationCompleted(e);
- }
-
- ///
- protected override void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e)
- {
- var horizontalChange = e.Delta.Translation.X;
- var verticalChange = e.Delta.Translation.Y;
-
- if (this.FlowDirection == FlowDirection.RightToLeft)
- {
- horizontalChange *= -1;
- }
-
- if (_resizeDirection == GridResizeDirection.Columns)
- {
- if (HorizontalMove(horizontalChange))
- {
- return;
- }
- }
- else if (_resizeDirection == GridResizeDirection.Rows)
- {
- if (VerticalMove(verticalChange))
- {
- return;
- }
- }
-
- base.OnManipulationDelta(e);
- }
-
- private bool VerticalMove(double verticalChange)
- {
- if (CurrentRow == null || SiblingRow == null)
- {
- return true;
- }
-
- // if current row has fixed height then resize it
- if (!IsStarRow(CurrentRow))
- {
- // No need to check for the row Min height because it is automatically respected
- if (!SetRowHeight(CurrentRow, verticalChange, GridUnitType.Pixel))
- {
- return true;
- }
- }
-
- // if sibling row has fixed width then resize it
- else if (!IsStarRow(SiblingRow))
- {
- // Would adding to this column make the current column violate the MinWidth?
- if (IsValidRowHeight(CurrentRow, verticalChange) == false)
- {
- return false;
- }
-
- if (!SetRowHeight(SiblingRow, verticalChange * -1, GridUnitType.Pixel))
- {
- return true;
- }
- }
-
- // if both row haven't fixed height (auto *)
- else
- {
- // change current row height to the new height with respecting the auto
- // change sibling row height to the new height relative to current row
- // respect the other star row height by setting it's height to it's actual height with stars
-
- // We need to validate current and sibling height to not cause any unexpected behavior
- if (!IsValidRowHeight(CurrentRow, verticalChange) ||
- !IsValidRowHeight(SiblingRow, verticalChange * -1))
- {
- return true;
- }
-
- foreach (var rowDefinition in Resizable.RowDefinitions)
- {
- if (rowDefinition == CurrentRow)
- {
- SetRowHeight(CurrentRow, verticalChange, GridUnitType.Star);
- }
- else if (rowDefinition == SiblingRow)
- {
- SetRowHeight(SiblingRow, verticalChange * -1, GridUnitType.Star);
- }
- else if (IsStarRow(rowDefinition))
- {
- rowDefinition.Height = new GridLength(rowDefinition.ActualHeight, GridUnitType.Star);
- }
- }
- }
-
- return false;
- }
-
- private bool HorizontalMove(double horizontalChange)
- {
- if (CurrentColumn == null || SiblingColumn == null)
- {
- return true;
- }
-
- // if current column has fixed width then resize it
- if (!IsStarColumn(CurrentColumn))
- {
- // No need to check for the Column Min width because it is automatically respected
- if (!SetColumnWidth(CurrentColumn, horizontalChange, GridUnitType.Pixel))
- {
- return true;
- }
- }
-
- // if sibling column has fixed width then resize it
- else if (!IsStarColumn(SiblingColumn))
- {
- // Would adding to this column make the current column violate the MinWidth?
- if (IsValidColumnWidth(CurrentColumn, horizontalChange) == false)
- {
- return false;
- }
-
- if (!SetColumnWidth(SiblingColumn, horizontalChange * -1, GridUnitType.Pixel))
- {
- return true;
- }
- }
-
- // if both column haven't fixed width (auto *)
- else
- {
- // change current column width to the new width with respecting the auto
- // change sibling column width to the new width relative to current column
- // respect the other star column width by setting it's width to it's actual width with stars
-
- // We need to validate current and sibling width to not cause any unexpected behavior
- if (!IsValidColumnWidth(CurrentColumn, horizontalChange) ||
- !IsValidColumnWidth(SiblingColumn, horizontalChange * -1))
- {
- return true;
- }
-
- foreach (var columnDefinition in Resizable.ColumnDefinitions)
- {
- if (columnDefinition == CurrentColumn)
- {
- SetColumnWidth(CurrentColumn, horizontalChange, GridUnitType.Star);
- }
- else if (columnDefinition == SiblingColumn)
- {
- SetColumnWidth(SiblingColumn, horizontalChange * -1, GridUnitType.Star);
- }
- else if (IsStarColumn(columnDefinition))
- {
- columnDefinition.Width = new GridLength(columnDefinition.ActualWidth, GridUnitType.Star);
- }
- }
- }
-
- return false;
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Options.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Options.cs
deleted file mode 100644
index 5564c0336c7..00000000000
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Options.cs
+++ /dev/null
@@ -1,229 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Windows.UI.Core;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Media;
-
-namespace Microsoft.Toolkit.Uwp.UI.Controls
-{
- ///
- /// Represents the control that redistributes space between columns or rows of a Grid control.
- ///
- public partial class GridSplitter
- {
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ElementProperty
- = DependencyProperty.Register(
- nameof(Element),
- typeof(UIElement),
- typeof(GridSplitter),
- new PropertyMetadata(default(UIElement), OnElementPropertyChanged));
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ResizeDirectionProperty
- = DependencyProperty.Register(
- nameof(ResizeDirection),
- typeof(GridResizeDirection),
- typeof(GridSplitter),
- new PropertyMetadata(GridResizeDirection.Auto));
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ResizeBehaviorProperty
- = DependencyProperty.Register(
- nameof(ResizeBehavior),
- typeof(GridResizeBehavior),
- typeof(GridSplitter),
- new PropertyMetadata(GridResizeBehavior.BasedOnAlignment));
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty GripperForegroundProperty
- = DependencyProperty.Register(
- nameof(GripperForeground),
- typeof(Brush),
- typeof(GridSplitter),
- new PropertyMetadata(default(Brush), OnGripperForegroundPropertyChanged));
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty ParentLevelProperty
- = DependencyProperty.Register(
- nameof(ParentLevel),
- typeof(int),
- typeof(GridSplitter),
- new PropertyMetadata(default(int)));
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty GripperCursorProperty =
- DependencyProperty.RegisterAttached(
- nameof(GripperCursor),
- typeof(CoreCursorType?),
- typeof(GridSplitter),
- new PropertyMetadata(GripperCursorType.Default, OnGripperCursorPropertyChanged));
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty GripperCustomCursorResourceProperty =
- DependencyProperty.RegisterAttached(
- nameof(GripperCustomCursorResource),
- typeof(uint),
- typeof(GridSplitter),
- new PropertyMetadata(GripperCustomCursorDefaultResource, GripperCustomCursorResourcePropertyChanged));
-
- ///
- /// Identifies the dependency property.
- ///
- public static readonly DependencyProperty CursorBehaviorProperty =
- DependencyProperty.RegisterAttached(
- nameof(CursorBehavior),
- typeof(SplitterCursorBehavior),
- typeof(GridSplitter),
- new PropertyMetadata(SplitterCursorBehavior.ChangeOnSplitterHover, CursorBehaviorPropertyChanged));
-
- ///
- /// Gets or sets the visual content of this Grid Splitter
- ///
- public UIElement Element
- {
- get { return (UIElement)GetValue(ElementProperty); }
- set { SetValue(ElementProperty, value); }
- }
-
- ///
- /// Gets or sets whether the Splitter resizes the Columns, Rows, or Both.
- ///
- public GridResizeDirection ResizeDirection
- {
- get { return (GridResizeDirection)GetValue(ResizeDirectionProperty); }
-
- set { SetValue(ResizeDirectionProperty, value); }
- }
-
- ///
- /// Gets or sets which Columns or Rows the Splitter resizes.
- ///
- public GridResizeBehavior ResizeBehavior
- {
- get { return (GridResizeBehavior)GetValue(ResizeBehaviorProperty); }
-
- set { SetValue(ResizeBehaviorProperty, value); }
- }
-
- ///
- /// Gets or sets the foreground color of grid splitter grip
- ///
- public Brush GripperForeground
- {
- get { return (Brush)GetValue(GripperForegroundProperty); }
-
- set { SetValue(GripperForegroundProperty, value); }
- }
-
- ///
- /// Gets or sets the level of the parent grid to resize
- ///
- public int ParentLevel
- {
- get { return (int)GetValue(ParentLevelProperty); }
-
- set { SetValue(ParentLevelProperty, value); }
- }
-
- ///
- /// Gets or sets the gripper Cursor type
- ///
- public GripperCursorType GripperCursor
- {
- get { return (GripperCursorType)GetValue(GripperCursorProperty); }
- set { SetValue(GripperCursorProperty, value); }
- }
-
- ///
- /// Gets or sets the gripper Custom Cursor resource number
- ///
- public int GripperCustomCursorResource
- {
- get { return (int)GetValue(GripperCustomCursorResourceProperty); }
- set { SetValue(GripperCustomCursorResourceProperty, value); }
- }
-
- ///
- /// Gets or sets splitter cursor on hover behavior
- ///
- public SplitterCursorBehavior CursorBehavior
- {
- get { return (SplitterCursorBehavior)GetValue(CursorBehaviorProperty); }
- set { SetValue(CursorBehaviorProperty, value); }
- }
-
- private static void OnGripperForegroundPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var gridSplitter = (GridSplitter)d;
-
- if (gridSplitter._gripperDisplay == null)
- {
- return;
- }
-
- gridSplitter._gripperDisplay.Foreground = gridSplitter.GripperForeground;
- }
-
- private static void OnGripperCursorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var gridSplitter = (GridSplitter)d;
-
- if (gridSplitter._hoverWrapper == null)
- {
- return;
- }
-
- gridSplitter._hoverWrapper.GripperCursor = gridSplitter.GripperCursor;
- }
-
- private static void GripperCustomCursorResourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var gridSplitter = (GridSplitter)d;
-
- if (gridSplitter._hoverWrapper == null)
- {
- return;
- }
-
- gridSplitter._hoverWrapper.GripperCustomCursorResource = gridSplitter.GripperCustomCursorResource;
- }
-
- private static void CursorBehaviorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var gridSplitter = (GridSplitter)d;
-
- gridSplitter._hoverWrapper?.UpdateHoverElement(gridSplitter.CursorBehavior ==
- SplitterCursorBehavior.ChangeOnSplitterHover
- ? gridSplitter
- : gridSplitter.Element);
- }
-
- private static void OnElementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var gridSplitter = (GridSplitter)d;
-
- gridSplitter._hoverWrapper?.UpdateHoverElement(gridSplitter.CursorBehavior ==
- SplitterCursorBehavior.ChangeOnSplitterHover
- ? gridSplitter
- : gridSplitter.Element);
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.xaml b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.xaml
deleted file mode 100644
index 451e054d16f..00000000000
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.xaml
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GripperHoverWrapper.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GripperHoverWrapper.cs
deleted file mode 100644
index 6b22b204886..00000000000
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GripperHoverWrapper.cs
+++ /dev/null
@@ -1,169 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Windows.UI.Core;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Input;
-
-namespace Microsoft.Toolkit.Uwp.UI.Controls
-{
- internal class GripperHoverWrapper
- {
- private readonly GridSplitter.GridResizeDirection _gridSplitterDirection;
-
- private CoreCursor _splitterPreviousPointer;
- private CoreCursor _previousCursor;
- private GridSplitter.GripperCursorType _gripperCursor;
- private int _gripperCustomCursorResource;
- private bool _isDragging;
- private UIElement _element;
-
- internal GridSplitter.GripperCursorType GripperCursor
- {
- get
- {
- return _gripperCursor;
- }
-
- set
- {
- _gripperCursor = value;
- }
- }
-
- internal int GripperCustomCursorResource
- {
- get
- {
- return _gripperCustomCursorResource;
- }
-
- set
- {
- _gripperCustomCursorResource = value;
- }
- }
-
- ///
- /// Initializes a new instance of the class that add cursor change on hover functionality for GridSplitter.
- ///
- /// UI element to apply cursor change on hover
- /// GridSplitter resize direction
- /// GridSplitter gripper on hover cursor type
- /// GridSplitter gripper custom cursor resource number
- internal GripperHoverWrapper(UIElement element, GridSplitter.GridResizeDirection gridSplitterDirection, GridSplitter.GripperCursorType gripperCursor, int gripperCustomCursorResource)
- {
- _gridSplitterDirection = gridSplitterDirection;
- _gripperCursor = gripperCursor;
- _gripperCustomCursorResource = gripperCustomCursorResource;
- _element = element;
- UnhookEvents();
- _element.PointerEntered += Element_PointerEntered;
- _element.PointerExited += Element_PointerExited;
- }
-
- internal void UpdateHoverElement(UIElement element)
- {
- UnhookEvents();
- _element = element;
- _element.PointerEntered += Element_PointerEntered;
- _element.PointerExited += Element_PointerExited;
- }
-
- private void Element_PointerExited(object sender, PointerRoutedEventArgs e)
- {
- if (_isDragging)
- {
- // if dragging don't update the cursor just update the splitter cursor with the last window cursor,
- // because the splitter is still using the arrow cursor and will revert to original case when drag completes
- _splitterPreviousPointer = _previousCursor;
- }
- else
- {
- Window.Current.CoreWindow.PointerCursor = _previousCursor;
- }
- }
-
- private void Element_PointerEntered(object sender, PointerRoutedEventArgs e)
- {
- // if not dragging
- if (!_isDragging)
- {
- _previousCursor = _splitterPreviousPointer = Window.Current.CoreWindow.PointerCursor;
- UpdateDisplayCursor();
- }
-
- // if dragging
- else
- {
- _previousCursor = _splitterPreviousPointer;
- }
- }
-
- private void UpdateDisplayCursor()
- {
- if (_gripperCursor == GridSplitter.GripperCursorType.Default)
- {
- if (_gridSplitterDirection == GridSplitter.GridResizeDirection.Columns)
- {
- Window.Current.CoreWindow.PointerCursor = GridSplitter.ColumnsSplitterCursor;
- }
- else if (_gridSplitterDirection == GridSplitter.GridResizeDirection.Rows)
- {
- Window.Current.CoreWindow.PointerCursor = GridSplitter.RowSplitterCursor;
- }
- }
- else
- {
- var coreCursor = (CoreCursorType)((int)_gripperCursor);
- if (_gripperCursor == GridSplitter.GripperCursorType.Custom)
- {
- if (_gripperCustomCursorResource > GridSplitter.GripperCustomCursorDefaultResource)
- {
- Window.Current.CoreWindow.PointerCursor = new CoreCursor(coreCursor, (uint)_gripperCustomCursorResource);
- }
- }
- else
- {
- Window.Current.CoreWindow.PointerCursor = new CoreCursor(coreCursor, 1);
- }
- }
- }
-
- internal void SplitterManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
- {
- var splitter = sender as GridSplitter;
- if (splitter == null)
- {
- return;
- }
-
- _splitterPreviousPointer = splitter.PreviousCursor;
- _isDragging = true;
- }
-
- internal void SplitterManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
- {
- var splitter = sender as GridSplitter;
- if (splitter == null)
- {
- return;
- }
-
- Window.Current.CoreWindow.PointerCursor = splitter.PreviousCursor = _splitterPreviousPointer;
- _isDragging = false;
- }
-
- internal void UnhookEvents()
- {
- if (_element == null)
- {
- return;
- }
-
- _element.PointerEntered -= Element_PointerEntered;
- _element.PointerExited -= Element_PointerExited;
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer/ContentSizer.Events.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer/ContentSizer.Events.cs
new file mode 100644
index 00000000000..18b797dda16
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer/ContentSizer.Events.cs
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Toolkit.Uwp.UI;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Events for .
+ ///
+ public partial class ContentSizer
+ {
+ ///
+ protected override void OnLoaded(RoutedEventArgs e)
+ {
+ if (TargetControl == null)
+ {
+ TargetControl = this.FindAscendant();
+ }
+ }
+
+ private double _currentSize;
+
+ ///
+ protected override void OnDragStarting()
+ {
+ if (TargetControl != null)
+ {
+ _currentSize =
+ Orientation == Orientation.Vertical ?
+ TargetControl.ActualWidth :
+ TargetControl.ActualHeight;
+ }
+ }
+
+ ///
+ protected override bool OnDragHorizontal(double horizontalChange)
+ {
+ if (TargetControl == null)
+ {
+ return true;
+ }
+
+ horizontalChange = IsDragInverted ? -horizontalChange : horizontalChange;
+
+ if (!IsValidWidth(TargetControl, _currentSize + horizontalChange, ActualWidth))
+ {
+ return false;
+ }
+
+ TargetControl.Width = _currentSize + horizontalChange;
+
+ return true;
+ }
+
+ ///
+ protected override bool OnDragVertical(double verticalChange)
+ {
+ if (TargetControl == null)
+ {
+ return false;
+ }
+
+ verticalChange = IsDragInverted ? -verticalChange : verticalChange;
+
+ if (!IsValidHeight(TargetControl, _currentSize + verticalChange, ActualHeight))
+ {
+ return false;
+ }
+
+ TargetControl.Height = _currentSize + verticalChange;
+
+ return true;
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer/ContentSizer.Properties.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer/ContentSizer.Properties.cs
new file mode 100644
index 00000000000..f9f410d547d
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer/ContentSizer.Properties.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Properties for .
+ ///
+ public partial class ContentSizer
+ {
+ ///
+ /// Gets or sets a value indicating whether the control is resizing in the opposite direction.
+ ///
+ public bool IsDragInverted
+ {
+ get { return (bool)GetValue(IsDragInvertedProperty); }
+ set { SetValue(IsDragInvertedProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty IsDragInvertedProperty =
+ DependencyProperty.Register(nameof(IsDragInverted), typeof(bool), typeof(ContentSizer), new PropertyMetadata(false));
+
+ ///
+ /// Gets or sets the control that the is resizing. Be default, this will be the visual ancestor of the .
+ ///
+ public FrameworkElement TargetControl
+ {
+ get { return (FrameworkElement)GetValue(TargetControlProperty); }
+ set { SetValue(TargetControlProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty TargetControlProperty =
+ DependencyProperty.Register(nameof(TargetControl), typeof(FrameworkElement), typeof(ContentSizer), new PropertyMetadata(null, OnTargetControlChanged));
+
+ private static void OnTargetControlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ // TODO: Should we do this after the TargetControl is Loaded? (And use ActualWidth?)
+ // Or should we just do it in the manipulation event if Width is null?
+
+ // Check if our width can be manipulated
+ if (d is SizerBase splitterBase && e.NewValue is FrameworkElement element)
+ {
+ // TODO: For Auto ResizeDirection we might want to do detection logic (TBD) here first?
+ if (splitterBase.Orientation != Orientation.Horizontal && double.IsNaN(element.Width))
+ {
+ // We need to set the Width or Height somewhere,
+ // as if it's NaN we won't be able to manipulate it.
+ element.Width = element.DesiredSize.Width;
+ }
+
+ if (splitterBase.Orientation != Orientation.Vertical && double.IsNaN(element.Height))
+ {
+ element.Height = element.DesiredSize.Height;
+ }
+ }
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer/ContentSizer.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer/ContentSizer.cs
new file mode 100644
index 00000000000..bcaba6a0272
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/ContentSizer/ContentSizer.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Windows.UI.Xaml.Controls;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// The is a control which can be used to resize any element, usually its parent. If you are using a , use instead.
+ ///
+ public partial class ContentSizer : SizerBase
+ {
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Data.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Data.cs
new file mode 100644
index 00000000000..477640824a1
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Data.cs
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Represents the control that redistributes space between columns or rows of a Grid control.
+ ///
+ public partial class GridSplitter
+ {
+ ///
+ /// Enum to indicate whether GridSplitter resizes Columns or Rows
+ ///
+ public enum GridResizeDirection
+ {
+ ///
+ /// Determines whether to resize rows or columns based on its Alignment and
+ /// width compared to height
+ ///
+ Auto,
+
+ ///
+ /// Resize columns when dragging Splitter.
+ ///
+ Columns,
+
+ ///
+ /// Resize rows when dragging Splitter.
+ ///
+ Rows
+ }
+
+ ///
+ /// Enum to indicate what Columns or Rows the GridSplitter resizes
+ ///
+ public enum GridResizeBehavior
+ {
+ ///
+ /// Determine which columns or rows to resize based on its Alignment.
+ ///
+ BasedOnAlignment,
+
+ ///
+ /// Resize the current and next Columns or Rows.
+ ///
+ CurrentAndNext,
+
+ ///
+ /// Resize the previous and current Columns or Rows.
+ ///
+ PreviousAndCurrent,
+
+ ///
+ /// Resize the previous and next Columns or Rows.
+ ///
+ PreviousAndNext
+ }
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Events.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Events.cs
new file mode 100644
index 00000000000..1ffab158fbd
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Events.cs
@@ -0,0 +1,179 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Windows.System;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Represents the control that redistributes space between columns or rows of a Grid control.
+ ///
+ public partial class GridSplitter
+ {
+ ///
+ protected override void OnLoaded(RoutedEventArgs e)
+ {
+ _resizeDirection = GetResizeDirection();
+ Orientation = _resizeDirection == GridResizeDirection.Rows ?
+ Orientation.Horizontal : Orientation.Vertical;
+ _resizeBehavior = GetResizeBehavior();
+ }
+
+ private double _currentSize;
+ private double _siblingSize;
+
+ ///
+ protected override void OnDragStarting()
+ {
+ _resizeDirection = GetResizeDirection();
+ Orientation = _resizeDirection == GridResizeDirection.Rows ?
+ Orientation.Horizontal : Orientation.Vertical;
+ _resizeBehavior = GetResizeBehavior();
+
+ // Record starting points
+ if (Orientation == Orientation.Horizontal)
+ {
+ _currentSize = CurrentRow?.ActualHeight ?? -1;
+ _siblingSize = SiblingRow?.ActualHeight ?? -1;
+ }
+ else
+ {
+ _currentSize = CurrentColumn?.ActualWidth ?? -1;
+ _siblingSize = SiblingColumn?.ActualWidth ?? -1;
+ }
+ }
+
+ ///
+ protected override bool OnDragVertical(double verticalChange)
+ {
+ if (CurrentRow == null || SiblingRow == null)
+ {
+ return false;
+ }
+
+ var currentChange = _currentSize + verticalChange;
+ var siblingChange = _siblingSize + (verticalChange * -1); // sibling moves opposite
+
+ // if current row has fixed height then resize it
+ if (!IsStarRow(CurrentRow))
+ {
+ // No need to check for the row Min height because it is automatically respected
+ return SetRowHeight(CurrentRow, currentChange, GridUnitType.Pixel);
+ }
+
+ // if sibling row has fixed width then resize it
+ else if (!IsStarRow(SiblingRow))
+ {
+ // Would adding to this column make the current column violate the MinWidth?
+ if (IsValidRowHeight(CurrentRow, currentChange) == false)
+ {
+ return false;
+ }
+
+ return SetRowHeight(SiblingRow, siblingChange, GridUnitType.Pixel);
+ }
+
+ // if both row haven't fixed height (auto *)
+ else
+ {
+ // change current row height to the new height with respecting the auto
+ // change sibling row height to the new height relative to current row
+ // respect the other star row height by setting it's height to it's actual height with stars
+
+ // We need to validate current and sibling height to not cause any unexpected behavior
+ if (!IsValidRowHeight(CurrentRow, currentChange) ||
+ !IsValidRowHeight(SiblingRow, siblingChange))
+ {
+ return false;
+ }
+
+ foreach (var rowDefinition in Resizable.RowDefinitions)
+ {
+ if (rowDefinition == CurrentRow)
+ {
+ SetRowHeight(CurrentRow, currentChange, GridUnitType.Star);
+ }
+ else if (rowDefinition == SiblingRow)
+ {
+ SetRowHeight(SiblingRow, siblingChange, GridUnitType.Star);
+ }
+ else if (IsStarRow(rowDefinition))
+ {
+ rowDefinition.Height = new GridLength(rowDefinition.ActualHeight, GridUnitType.Star);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ ///
+ protected override bool OnDragHorizontal(double horizontalChange)
+ {
+ if (CurrentColumn == null || SiblingColumn == null)
+ {
+ return false;
+ }
+
+ var currentChange = _currentSize + horizontalChange;
+ var siblingChange = _siblingSize + (horizontalChange * -1); // sibling moves opposite
+
+ // if current column has fixed width then resize it
+ if (!IsStarColumn(CurrentColumn))
+ {
+ // No need to check for the Column Min width because it is automatically respected
+ return SetColumnWidth(CurrentColumn, currentChange, GridUnitType.Pixel);
+ }
+
+ // if sibling column has fixed width then resize it
+ else if (!IsStarColumn(SiblingColumn))
+ {
+ // Would adding to this column make the current column violate the MinWidth?
+ if (IsValidColumnWidth(CurrentColumn, currentChange) == false)
+ {
+ return false;
+ }
+
+ return SetColumnWidth(SiblingColumn, siblingChange, GridUnitType.Pixel);
+ }
+
+ // if both column haven't fixed width (auto *)
+ else
+ {
+ // change current column width to the new width with respecting the auto
+ // change sibling column width to the new width relative to current column
+ // respect the other star column width by setting it's width to it's actual width with stars
+
+ // We need to validate current and sibling width to not cause any unexpected behavior
+ if (!IsValidColumnWidth(CurrentColumn, currentChange) ||
+ !IsValidColumnWidth(SiblingColumn, siblingChange))
+ {
+ return false;
+ }
+
+ foreach (var columnDefinition in Resizable.ColumnDefinitions)
+ {
+ if (columnDefinition == CurrentColumn)
+ {
+ SetColumnWidth(CurrentColumn, currentChange, GridUnitType.Star);
+ }
+ else if (columnDefinition == SiblingColumn)
+ {
+ SetColumnWidth(SiblingColumn, siblingChange, GridUnitType.Star);
+ }
+ else if (IsStarColumn(columnDefinition))
+ {
+ columnDefinition.Width = new GridLength(columnDefinition.ActualWidth, GridUnitType.Star);
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Helper.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Helpers.cs
similarity index 94%
rename from Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Helper.cs
rename to Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Helpers.cs
index 1b7496cded4..1f65b22f78c 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.Helper.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Helpers.cs
@@ -22,10 +22,8 @@ private static bool IsStarRow(RowDefinition definition)
return ((GridLength)definition.GetValue(RowDefinition.HeightProperty)).IsStar;
}
- private bool SetColumnWidth(ColumnDefinition columnDefinition, double horizontalChange, GridUnitType unitType)
+ private bool SetColumnWidth(ColumnDefinition columnDefinition, double newWidth, GridUnitType unitType)
{
- var newWidth = columnDefinition.ActualWidth + horizontalChange;
-
var minWidth = columnDefinition.MinWidth;
if (!double.IsNaN(minWidth) && newWidth < minWidth)
{
@@ -47,10 +45,8 @@ private bool SetColumnWidth(ColumnDefinition columnDefinition, double horizontal
return false;
}
- private bool IsValidColumnWidth(ColumnDefinition columnDefinition, double horizontalChange)
+ private bool IsValidColumnWidth(ColumnDefinition columnDefinition, double newWidth)
{
- var newWidth = columnDefinition.ActualWidth + horizontalChange;
-
var minWidth = columnDefinition.MinWidth;
if (!double.IsNaN(minWidth) && newWidth < minWidth)
{
@@ -71,10 +67,8 @@ private bool IsValidColumnWidth(ColumnDefinition columnDefinition, double horizo
return true;
}
- private bool SetRowHeight(RowDefinition rowDefinition, double verticalChange, GridUnitType unitType)
+ private bool SetRowHeight(RowDefinition rowDefinition, double newHeight, GridUnitType unitType)
{
- var newHeight = rowDefinition.ActualHeight + verticalChange;
-
var minHeight = rowDefinition.MinHeight;
if (!double.IsNaN(minHeight) && newHeight < minHeight)
{
@@ -96,10 +90,8 @@ private bool SetRowHeight(RowDefinition rowDefinition, double verticalChange, Gr
return false;
}
- private bool IsValidRowHeight(RowDefinition rowDefinition, double verticalChange)
+ private bool IsValidRowHeight(RowDefinition rowDefinition, double newHeight)
{
- var newHeight = rowDefinition.ActualHeight + verticalChange;
-
var minHeight = rowDefinition.MinHeight;
if (!double.IsNaN(minHeight) && newHeight < minHeight)
{
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Properties.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Properties.cs
new file mode 100644
index 00000000000..1ffcdbb4f92
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.Properties.cs
@@ -0,0 +1,87 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Represents the control that redistributes space between columns or rows of a Grid control.
+ ///
+ public partial class GridSplitter
+ {
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty ResizeDirectionProperty
+ = DependencyProperty.Register(
+ nameof(ResizeDirection),
+ typeof(GridResizeDirection),
+ typeof(GridSplitter),
+ new PropertyMetadata(GridResizeDirection.Auto, OnResizeDirectionPropertyChanged));
+
+ private static void OnResizeDirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is GridSplitter splitter && e.NewValue is GridResizeDirection direction &&
+ direction != GridResizeDirection.Auto)
+ {
+ // Update base classes property based on specific polyfill for GridSplitter
+ splitter.Orientation =
+ direction == GridResizeDirection.Rows ?
+ Orientation.Horizontal :
+ Orientation.Vertical;
+ }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty ResizeBehaviorProperty
+ = DependencyProperty.Register(
+ nameof(ResizeBehavior),
+ typeof(GridResizeBehavior),
+ typeof(GridSplitter),
+ new PropertyMetadata(GridResizeBehavior.BasedOnAlignment));
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty ParentLevelProperty
+ = DependencyProperty.Register(
+ nameof(ParentLevel),
+ typeof(int),
+ typeof(GridSplitter),
+ new PropertyMetadata(default(int)));
+
+ ///
+ /// Gets or sets whether the Splitter resizes the Columns, Rows, or Both.
+ ///
+ public GridResizeDirection ResizeDirection
+ {
+ get { return (GridResizeDirection)GetValue(ResizeDirectionProperty); }
+ set { SetValue(ResizeDirectionProperty, value); }
+ }
+
+ ///
+ /// Gets or sets which Columns or Rows the Splitter resizes.
+ ///
+ public GridResizeBehavior ResizeBehavior
+ {
+ get { return (GridResizeBehavior)GetValue(ResizeBehaviorProperty); }
+ set { SetValue(ResizeBehaviorProperty, value); }
+ }
+
+ ///
+ /// Gets or sets the level of the parent grid to resize
+ ///
+ public int ParentLevel
+ {
+ get { return (int)GetValue(ParentLevelProperty); }
+ set { SetValue(ParentLevelProperty, value); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.cs
similarity index 52%
rename from Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.cs
rename to Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.cs
index c6f807397aa..0a24643ae92 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/GridSplitter/GridSplitter.cs
@@ -2,33 +2,21 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Markup;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
///
/// Represents the control that redistributes space between columns or rows of a Grid control.
///
- public partial class GridSplitter : Control
+ public partial class GridSplitter : SizerBase
{
- internal const int GripperCustomCursorDefaultResource = -1;
- internal static readonly CoreCursor ColumnsSplitterCursor = new CoreCursor(CoreCursorType.SizeWestEast, 1);
- internal static readonly CoreCursor RowSplitterCursor = new CoreCursor(CoreCursorType.SizeNorthSouth, 1);
-
- internal CoreCursor PreviousCursor { get; set; }
-
private GridResizeDirection _resizeDirection;
private GridResizeBehavior _resizeBehavior;
- private GripperHoverWrapper _hoverWrapper;
- private TextBlock _gripperDisplay;
-
- private bool _pressed = false;
- private bool _dragging = false;
- private bool _pointerEntered = false;
///
/// Gets the target parent grid from level
@@ -156,91 +144,5 @@ private RowDefinition SiblingRow
return null;
}
}
-
- ///
- /// Initializes a new instance of the class.
- ///
- public GridSplitter()
- {
- DefaultStyleKey = typeof(GridSplitter);
- Loaded += GridSplitter_Loaded;
- string automationName = "WCT_GridSplitter_AutomationName".GetLocalized("Microsoft.Toolkit.Uwp.UI.Controls.Layout/Resources");
- AutomationProperties.SetName(this, automationName);
- }
-
- ///
- protected override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
-
- // Unhook registered events
- Loaded -= GridSplitter_Loaded;
- PointerEntered -= GridSplitter_PointerEntered;
- PointerExited -= GridSplitter_PointerExited;
- PointerPressed -= GridSplitter_PointerPressed;
- PointerReleased -= GridSplitter_PointerReleased;
- ManipulationStarted -= GridSplitter_ManipulationStarted;
- ManipulationCompleted -= GridSplitter_ManipulationCompleted;
-
- _hoverWrapper?.UnhookEvents();
-
- // Register Events
- Loaded += GridSplitter_Loaded;
- PointerEntered += GridSplitter_PointerEntered;
- PointerExited += GridSplitter_PointerExited;
- PointerPressed += GridSplitter_PointerPressed;
- PointerReleased += GridSplitter_PointerReleased;
- ManipulationStarted += GridSplitter_ManipulationStarted;
- ManipulationCompleted += GridSplitter_ManipulationCompleted;
-
- _hoverWrapper?.UpdateHoverElement(Element);
-
- ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
- }
-
- private void GridSplitter_PointerReleased(object sender, PointerRoutedEventArgs e)
- {
- _pressed = false;
- VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true);
- }
-
- private void GridSplitter_PointerPressed(object sender, PointerRoutedEventArgs e)
- {
- _pressed = true;
- VisualStateManager.GoToState(this, "Pressed", true);
- }
-
- private void GridSplitter_PointerExited(object sender, PointerRoutedEventArgs e)
- {
- _pointerEntered = false;
-
- if (!_pressed && !_dragging)
- {
- VisualStateManager.GoToState(this, "Normal", true);
- }
- }
-
- private void GridSplitter_PointerEntered(object sender, PointerRoutedEventArgs e)
- {
- _pointerEntered = true;
-
- if (!_pressed && !_dragging)
- {
- VisualStateManager.GoToState(this, "PointerOver", true);
- }
- }
-
- private void GridSplitter_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
- {
- _dragging = false;
- _pressed = false;
- VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true);
- }
-
- private void GridSplitter_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
- {
- _dragging = true;
- VisualStateManager.GoToState(this, "Pressed", true);
- }
}
}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer/PropertySizer.Events.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer/PropertySizer.Events.cs
new file mode 100644
index 00000000000..92f5bae1d83
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer/PropertySizer.Events.cs
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Toolkit.Uwp.UI;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Events for .
+ ///
+ public partial class PropertySizer
+ {
+ private double _currentSize;
+
+ ///
+ protected override void OnDragStarting()
+ {
+ // We grab the current size of the bound value when we start a drag
+ // and we manipulate from that set point.
+ if (ReadLocalValue(BindingProperty) != DependencyProperty.UnsetValue)
+ {
+ _currentSize = Binding;
+ }
+ }
+
+ ///
+ protected override bool OnDragHorizontal(double horizontalChange)
+ {
+ // We use a central function for both horizontal/vertical as
+ // a general property has no notion of direction when we
+ // manipulate it, so the logic is abstracted.
+ return ApplySizeChange(horizontalChange);
+ }
+
+ ///
+ protected override bool OnDragVertical(double verticalChange)
+ {
+ return ApplySizeChange(verticalChange);
+ }
+
+ private bool ApplySizeChange(double newSize)
+ {
+ newSize = IsDragInverted ? -newSize : newSize;
+
+ // We want to be checking the modified final value for bounds checks.
+ newSize += _currentSize;
+
+ // Check if we hit the min/max value, as we should use that if we're on the edge
+ if (ReadLocalValue(MinimumProperty) != DependencyProperty.UnsetValue &&
+ newSize < Minimum)
+ {
+ // We use SetValue here as that'll update our bound property vs. overwriting the binding itself.
+ SetValue(BindingProperty, Minimum);
+ }
+ else if (ReadLocalValue(MaximumProperty) != DependencyProperty.UnsetValue &&
+ newSize > Maximum)
+ {
+ SetValue(BindingProperty, Maximum);
+ }
+ else
+ {
+ // Otherwise, we use the value provided.
+ SetValue(BindingProperty, newSize);
+ }
+
+ // We're always manipulating the value effectively.
+ return true;
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer/PropertySizer.Properties.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer/PropertySizer.Properties.cs
new file mode 100644
index 00000000000..85ab278da8a
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer/PropertySizer.Properties.cs
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Properties for .
+ ///
+ public partial class PropertySizer
+ {
+ ///
+ /// Gets or sets a value indicating whether the control is resizing in the opposite direction.
+ ///
+ public bool IsDragInverted
+ {
+ get { return (bool)GetValue(IsDragInvertedProperty); }
+ set { SetValue(IsDragInvertedProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty IsDragInvertedProperty =
+ DependencyProperty.Register(nameof(IsDragInverted), typeof(bool), typeof(PropertySizer), new PropertyMetadata(false));
+
+ ///
+ /// Gets or sets a two-way binding to a double value that the is manipulating.
+ ///
+ ///
+ /// Note that the binding should be configured to be a TwoWay binding in order for the control to notify the source of the changed value.
+ ///
+ ///
+ /// <controls:PropertySizer Binding="{Binding OpenPaneLength, ElementName=ViewPanel, Mode=TwoWay}">
+ ///
+ public double Binding
+ {
+ get { return (double)GetValue(BindingProperty); }
+ set { SetValue(BindingProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty BindingProperty =
+ DependencyProperty.Register(nameof(Binding), typeof(double), typeof(PropertySizer), new PropertyMetadata(null));
+
+ ///
+ /// Gets or sets the minimum allowed value for the to allow for the value. Ignored if not provided.
+ ///
+ public double Minimum
+ {
+ get { return (double)GetValue(MinimumProperty); }
+ set { SetValue(MinimumProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty MinimumProperty =
+ DependencyProperty.Register(nameof(Minimum), typeof(double), typeof(PropertySizer), new PropertyMetadata(0));
+
+ ///
+ /// Gets or sets the maximum allowed value for the to allow for the value. Ignored if not provided.
+ ///
+ public double Maximum
+ {
+ get { return (double)GetValue(MaximumProperty); }
+ set { SetValue(MaximumProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty MaximumProperty =
+ DependencyProperty.Register(nameof(Maximum), typeof(double), typeof(PropertySizer), new PropertyMetadata(0));
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer/PropertySizer.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer/PropertySizer.cs
new file mode 100644
index 00000000000..3b951694314
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/PropertySizer/PropertySizer.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Windows.UI.Xaml.Controls;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// The is a control which can be used to manipulate the value of another double based property. For instance manipulating the OpenPaneLength of a NavigationView control. If you are using a , use instead.
+ ///
+ public partial class PropertySizer : SizerBase
+ {
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerAutomationPeer.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerAutomationPeer.cs
new file mode 100644
index 00000000000..c6e0170cd3e
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerAutomationPeer.cs
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Toolkit.Uwp.UI.Controls;
+using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Automation.Peers;
+
+namespace Microsoft.Toolkit.Uwp.UI.Automation.Peers
+{
+ ///
+ /// Defines a framework element automation peer for the controls.
+ ///
+ public class SizerAutomationPeer : FrameworkElementAutomationPeer
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The that is associated with this .
+ ///
+ public SizerAutomationPeer(SizerBase owner)
+ : base(owner)
+ {
+ }
+
+ private SizerBase OwningSizer
+ {
+ get
+ {
+ return Owner as SizerBase;
+ }
+ }
+
+ ///
+ /// Called by GetClassName that gets a human readable name that, in addition to AutomationControlType,
+ /// differentiates the control represented by this AutomationPeer.
+ ///
+ /// The string that contains the name.
+ protected override string GetClassNameCore()
+ {
+ return Owner.GetType().Name;
+ }
+
+ ///
+ /// Called by GetName.
+ ///
+ ///
+ /// Returns the first of these that is not null or empty:
+ /// - Value returned by the base implementation
+ /// - Name of the owning ContentSizer
+ /// - ContentSizer class name
+ ///
+ protected override string GetNameCore()
+ {
+ string name = AutomationProperties.GetName(this.OwningSizer);
+ if (!string.IsNullOrEmpty(name))
+ {
+ return name;
+ }
+
+ name = this.OwningSizer.Name;
+ if (!string.IsNullOrEmpty(name))
+ {
+ return name;
+ }
+
+ name = base.GetNameCore();
+ if (!string.IsNullOrEmpty(name))
+ {
+ return name;
+ }
+
+ return string.Empty;
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.Events.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.Events.cs
new file mode 100644
index 00000000000..f63cbe53765
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.Events.cs
@@ -0,0 +1,184 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Event implementations for .
+ ///
+ public partial class SizerBase
+ {
+ ///
+ protected override void OnKeyDown(KeyRoutedEventArgs e)
+ {
+ // If we're manipulating with mouse/touch, we ignore keyboard inputs.
+ if (_dragging)
+ {
+ return;
+ }
+
+ //// TODO: Do we want Ctrl/Shift to be a small increment (kind of inverse to old GridSplitter logic)?
+ //// var ctrl = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control);
+ //// if (ctrl.HasFlag(CoreVirtualKeyStates.Down))
+ //// Note: WPF doesn't do anything here.
+ //// I think if we did anything, we'd create a SmallKeyboardIncrement property?
+
+ // Initialize a drag event for this keyboard interaction.
+ OnDragStarting();
+
+ if (Orientation == Orientation.Vertical)
+ {
+ var horizontalChange = KeyboardIncrement;
+
+ // Important: adjust for RTL language flow settings and invert horizontal axis
+ if (this.FlowDirection == FlowDirection.RightToLeft)
+ {
+ horizontalChange *= -1;
+ }
+
+ if (e.Key == Windows.System.VirtualKey.Left)
+ {
+ OnDragHorizontal(-horizontalChange);
+ }
+ else if (e.Key == Windows.System.VirtualKey.Right)
+ {
+ OnDragHorizontal(horizontalChange);
+ }
+ }
+ else
+ {
+ if (e.Key == Windows.System.VirtualKey.Up)
+ {
+ OnDragVertical(-KeyboardIncrement);
+ }
+ else if (e.Key == Windows.System.VirtualKey.Down)
+ {
+ OnDragVertical(KeyboardIncrement);
+ }
+ }
+ }
+
+ ///
+ protected override void OnManipulationStarting(ManipulationStartingRoutedEventArgs e)
+ {
+ base.OnManipulationStarting(e);
+
+ OnDragStarting();
+ }
+
+ ///
+ protected override void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e)
+ {
+ // We use Trancate here to provide 'snapping' points with the DragIncrement property
+ // It works for both our negative and positive values, as otherwise we'd need to use
+ // Ceiling when negative and Floor when positive to maintain the correct behavior.
+ var horizontalChange =
+ Math.Truncate(e.Cumulative.Translation.X / DragIncrement) * DragIncrement;
+ var verticalChange =
+ Math.Truncate(e.Cumulative.Translation.Y / DragIncrement) * DragIncrement;
+
+ // Important: adjust for RTL language flow settings and invert horizontal axis
+ if (this.FlowDirection == FlowDirection.RightToLeft)
+ {
+ horizontalChange *= -1;
+ }
+
+ if (Orientation == Orientation.Vertical)
+ {
+ if (!OnDragHorizontal(horizontalChange))
+ {
+ return;
+ }
+ }
+ else if (Orientation == Orientation.Horizontal)
+ {
+ if (!OnDragVertical(verticalChange))
+ {
+ return;
+ }
+ }
+
+ base.OnManipulationDelta(e);
+ }
+
+ // private helper bools for Visual States
+ private bool _pressed = false;
+ private bool _dragging = false;
+ private bool _pointerEntered = false;
+
+ private void SizerBase_PointerReleased(object sender, PointerRoutedEventArgs e)
+ {
+ _pressed = false;
+
+ if (IsEnabled)
+ {
+ VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true);
+ }
+ }
+
+ private void SizerBase_PointerPressed(object sender, PointerRoutedEventArgs e)
+ {
+ _pressed = true;
+
+ if (IsEnabled)
+ {
+ VisualStateManager.GoToState(this, "Pressed", true);
+ }
+ }
+
+ private void SizerBase_PointerExited(object sender, PointerRoutedEventArgs e)
+ {
+ _pointerEntered = false;
+
+ if (!_pressed && !_dragging && IsEnabled)
+ {
+ VisualStateManager.GoToState(this, "Normal", true);
+ }
+ }
+
+ private void SizerBase_PointerEntered(object sender, PointerRoutedEventArgs e)
+ {
+ _pointerEntered = true;
+
+ if (!_pressed && !_dragging && IsEnabled)
+ {
+ VisualStateManager.GoToState(this, "PointerOver", true);
+ }
+ }
+
+ private void SizerBase_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
+ {
+ _dragging = false;
+ _pressed = false;
+ VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true);
+ }
+
+ private void SizerBase_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
+ {
+ _dragging = true;
+ VisualStateManager.GoToState(this, "Pressed", true);
+ }
+
+ private void SizerBase_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ if (!IsEnabled)
+ {
+ VisualStateManager.GoToState(this, "Disabled", true);
+ }
+ else
+ {
+ VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true);
+ }
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.Helpers.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.Helpers.cs
new file mode 100644
index 00000000000..95eb3123ab6
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.Helpers.cs
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Markup;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Protected helper methods for and subclasses.
+ ///
+ public partial class SizerBase : Control
+ {
+ ///
+ /// Check for new requested vertical size is valid or not
+ ///
+ /// Target control being resized
+ /// The requested new height
+ /// The parent control's ActualHeight
+ /// Bool result if requested vertical change is valid or not
+ protected static bool IsValidHeight(FrameworkElement target, double newHeight, double parentActualHeight)
+ {
+ var minHeight = target.MinHeight;
+ if (newHeight < 0 || (!double.IsNaN(minHeight) && newHeight < minHeight))
+ {
+ return false;
+ }
+
+ var maxHeight = target.MaxHeight;
+ if (!double.IsNaN(maxHeight) && newHeight > maxHeight)
+ {
+ return false;
+ }
+
+ if (newHeight <= parentActualHeight)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ /// Check for new requested horizontal size is valid or not
+ ///
+ /// Target control being resized
+ /// The requested new width
+ /// The parent control's ActualWidth
+ /// Bool result if requested horizontal change is valid or not
+ protected static bool IsValidWidth(FrameworkElement target, double newWidth, double parentActualWidth)
+ {
+ var minWidth = target.MinWidth;
+ if (newWidth < 0 || (!double.IsNaN(minWidth) && newWidth < minWidth))
+ {
+ return false;
+ }
+
+ var maxWidth = target.MaxWidth;
+ if (!double.IsNaN(maxWidth) && newWidth > maxWidth)
+ {
+ return false;
+ }
+
+ if (newWidth <= parentActualWidth)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.Properties.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.Properties.cs
new file mode 100644
index 00000000000..bae430e628c
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.Properties.cs
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Markup;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Properties for
+ ///
+ public partial class SizerBase : Control
+ {
+ ///
+ /// Gets or sets the cursor to use when hovering over the gripper bar.
+ ///
+ public CoreCursorType Cursor
+ {
+ get { return (CoreCursorType)GetValue(CursorProperty); }
+ set { SetValue(CursorProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty CursorProperty =
+ DependencyProperty.Register(nameof(Cursor), typeof(CoreCursorType), typeof(SizerBase), new PropertyMetadata(CoreCursorType.SizeWestEast));
+
+ ///
+ /// Gets or sets the incremental amount of change for draging with the mouse or touch of a sizer control. Effectively a snapping increment for changes. The default is 1.
+ ///
+ ///
+ /// For instance, if the DragIncrement is set to 16. Then when a component is resized with the sizer, it will only increase or decrease in size in that increment. I.e. -16, 0, 16, 32, 48, etc...
+ ///
+ ///
+ /// This value is indepedent of the property. If you need to provide consistent snapping when moving regardless of input device, set these properties to the same value.
+ ///
+ public double DragIncrement
+ {
+ get { return (double)GetValue(DragIncrementProperty); }
+ set { SetValue(DragIncrementProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty DragIncrementProperty =
+ DependencyProperty.Register(nameof(DragIncrement), typeof(double), typeof(SizerBase), new PropertyMetadata(1d));
+
+ ///
+ /// Gets or sets the distance each press of an arrow key moves a sizer control. The default is 8.
+ ///
+ ///
+ /// This value is independent of the setting when using mouse/touch. If you want a consistent behavior regardless of input device, set them to the same value if snapping is required.
+ ///
+ public double KeyboardIncrement
+ {
+ get { return (double)GetValue(KeyboardIncrementProperty); }
+ set { SetValue(KeyboardIncrementProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty KeyboardIncrementProperty =
+ DependencyProperty.Register(nameof(KeyboardIncrement), typeof(double), typeof(SizerBase), new PropertyMetadata(8d));
+
+ ///
+ /// Gets or sets the orientation the sizer will be and how it will interact with other elements. Defaults to .
+ ///
+ ///
+ /// Note if using , use the property instead.
+ ///
+ public Orientation Orientation
+ {
+ get { return (Orientation)GetValue(OrientationProperty); }
+ set { SetValue(OrientationProperty, value); }
+ }
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ public static readonly DependencyProperty OrientationProperty =
+ DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(SizerBase), new PropertyMetadata(Orientation.Vertical, OnOrientationPropertyChanged));
+
+ private static void OnOrientationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is SizerBase gripper)
+ {
+ // TODO: For WinUI 3, we will just be setting the ProtectedCursor property directly.
+ gripper.Cursor = gripper.Orientation == Orientation.Vertical ? CoreCursorType.SizeWestEast : CoreCursorType.SizeNorthSouth;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.cs
new file mode 100644
index 00000000000..1bff9578481
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.cs
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Toolkit.Uwp.UI.Automation.Peers;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Automation.Peers;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Base class for splitting/resizing type controls like and . Acts similar to an enlarged type control, but with keyboard support. Subclasses should override the various abstract methods here to implement their behavior.
+ ///
+ public abstract partial class SizerBase : Control
+ {
+ ///
+ /// Called when the control has been initialized.
+ ///
+ /// Loaded event args.
+ protected virtual void OnLoaded(RoutedEventArgs e)
+ {
+ }
+
+ ///
+ /// Called when the control starts to be dragged by the user.
+ /// Implementor should record current state of manipulated target at this point in time.
+ /// They will receive the cumulative change in or
+ /// based on the property.
+ ///
+ ///
+ /// This method is also called at the start of a keyboard interaction. Keyboard strokes use the same pattern to emulate a mouse movement for a single change. The appropriate
+ /// or
+ /// method will also be called after when the keyboard is used.
+ ///
+ protected abstract void OnDragStarting();
+
+ ///
+ /// Method to process the requested horizontal resize.
+ ///
+ /// The horizontal change amount from the start in device-independent pixels DIP.
+ /// indicates if a change was made
+ ///
+ /// The value provided here is the cumulative change from the beginning of the
+ /// manipulation. This method will be used regardless of input device. It will already
+ /// be adjusted for RightToLeft of the containing
+ /// layout/settings. It will also already account for any settings such as
+ /// or . The implementor
+ /// just needs to use the provided value to manipulate their baseline stored
+ /// in to provide the desired change.
+ ///
+ protected abstract bool OnDragHorizontal(double horizontalChange);
+
+ ///
+ /// Method to process the requested vertical resize.
+ ///
+ /// The vertical change amount from the start in device-independent pixels DIP.
+ /// indicates if a change was made
+ ///
+ /// The value provided here is the cumulative change from the beginning of the
+ /// manipulation. This method will be used regardless of input device. It will also
+ /// already account for any settings such as or
+ /// . The implementor just needs
+ /// to use the provided value to manipulate their baseline stored
+ /// in to provide the desired change.
+ ///
+ protected abstract bool OnDragVertical(double verticalChange);
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SizerBase()
+ {
+ this.DefaultStyleKey = typeof(SizerBase);
+ }
+
+ ///
+ /// Creates AutomationPeer ()
+ ///
+ /// An automation peer for this .
+ protected override AutomationPeer OnCreateAutomationPeer()
+ {
+ return new SizerAutomationPeer(this);
+ }
+
+ ///
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ // Unregister Events
+ Loaded -= SizerBase_Loaded;
+ PointerEntered -= SizerBase_PointerEntered;
+ PointerExited -= SizerBase_PointerExited;
+ PointerPressed -= SizerBase_PointerPressed;
+ PointerReleased -= SizerBase_PointerReleased;
+ ManipulationStarted -= SizerBase_ManipulationStarted;
+ ManipulationCompleted -= SizerBase_ManipulationCompleted;
+ IsEnabledChanged -= SizerBase_IsEnabledChanged;
+
+ // Register Events
+ Loaded += SizerBase_Loaded;
+ PointerEntered += SizerBase_PointerEntered;
+ PointerExited += SizerBase_PointerExited;
+ PointerPressed += SizerBase_PointerPressed;
+ PointerReleased += SizerBase_PointerReleased;
+ ManipulationStarted += SizerBase_ManipulationStarted;
+ ManipulationCompleted += SizerBase_ManipulationCompleted;
+ IsEnabledChanged += SizerBase_IsEnabledChanged;
+
+ // Trigger initial state transition based on if we're Enabled or not currently.
+ SizerBase_IsEnabledChanged(this, null);
+ }
+
+ private void SizerBase_Loaded(object sender, RoutedEventArgs e)
+ {
+ Loaded -= SizerBase_Loaded;
+
+ OnLoaded(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.xaml b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.xaml
new file mode 100644
index 00000000000..cb172b31770
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Sizers/SizerBase.xaml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Strings/en-US/Resources.resw b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Strings/en-US/Resources.resw
index 49a13464e39..d9201f3ce36 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Strings/en-US/Resources.resw
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Strings/en-US/Resources.resw
@@ -65,8 +65,8 @@
Expand Blade
Narrator Resource for BladeView expanded status
-
- GridSplitter
- Narrator Resource for GridSplitter control
+
+ Sizer
+ Narrator Resource for SizerBase controls and similar
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Themes/Generic.xaml b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Themes/Generic.xaml
index fd84465abdd..e3c125d8774 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Themes/Generic.xaml
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/Themes/Generic.xaml
@@ -4,11 +4,11 @@
-
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI/Converters/OrientationToObjectConverter.cs b/Microsoft.Toolkit.Uwp.UI/Converters/OrientationToObjectConverter.cs
new file mode 100644
index 00000000000..65d152d168d
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI/Converters/OrientationToObjectConverter.cs
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Data;
+
+namespace Microsoft.Toolkit.Uwp.UI.Converters
+{
+ ///
+ /// This class returns a value depending on the of the value provided to the converter. In case of default will return the .
+ ///
+ public partial class OrientationToObjectConverter : DependencyObject, IValueConverter
+ {
+ ///
+ /// Identifies the property.
+ ///
+ public static readonly DependencyProperty HorizontalValueProperty =
+ DependencyProperty.Register(nameof(HorizontalValue), typeof(object), typeof(TypeToObjectConverter), new PropertyMetadata(null));
+
+ ///
+ /// Identifies the property.
+ ///
+ public static readonly DependencyProperty VerticalValueProperty =
+ DependencyProperty.Register(nameof(VerticalValue), typeof(object), typeof(TypeToObjectConverter), new PropertyMetadata(null));
+
+ ///
+ /// Gets or sets the value to be returned when the of the provided value is .
+ ///
+ public object HorizontalValue
+ {
+ get { return GetValue(HorizontalValueProperty); }
+ set { SetValue(HorizontalValueProperty, value); }
+ }
+
+ ///
+ /// Gets or sets the value to be returned when the of the provided value is .
+ ///
+ public object VerticalValue
+ {
+ get { return GetValue(VerticalValueProperty); }
+ set { SetValue(VerticalValueProperty, value); }
+ }
+
+ ///
+ /// Convert the 's Orientation to an other object.
+ ///
+ /// The source data being passed to the target.
+ /// The type of the target property, as a type reference.
+ /// An optional parameter to be used to invert the converter logic.
+ /// The language of the conversion.
+ /// The value to be passed to the target dependency property.
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var isHorizontal = value != null && value is Orientation orientation && orientation == Orientation.Horizontal;
+
+ // Negate if needed
+ if (ConverterTools.TryParseBool(parameter))
+ {
+ isHorizontal = !isHorizontal;
+ }
+
+ return ConverterTools.Convert(isHorizontal ? HorizontalValue : VerticalValue, targetType);
+ }
+
+ ///
+ /// Not implemented.
+ ///
+ /// The source data being passed to the target.
+ /// The type of the target property, as a type reference.
+ /// Optional parameter. Not used.
+ /// The language of the conversion. Not used.
+ /// The value to be passed to the target dependency property.
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml b/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml
index 09236488742..c0e6da4750e 100644
--- a/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml
+++ b/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml
@@ -81,14 +81,6 @@
Grid.ColumnSpan="3"
Height="16"
VerticalAlignment="Top">
-
-
-
diff --git a/UnitTests/UnitTests.UWP/Converters/Test_OrientationToObjectConverter.cs b/UnitTests/UnitTests.UWP/Converters/Test_OrientationToObjectConverter.cs
new file mode 100644
index 00000000000..8b7806cd2c0
--- /dev/null
+++ b/UnitTests/UnitTests.UWP/Converters/Test_OrientationToObjectConverter.cs
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Toolkit.Uwp.UI.Converters;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace UnitTests.Converters
+{
+ [TestClass]
+ public class Test_OrientationToObjectConverter
+ {
+ [TestCategory("Converters")]
+ [UITestMethod]
+ public void Test_OrientationConvertNullToString()
+ {
+ var converter = new OrientationToObjectConverter
+ {
+ HorizontalValue = "Horizontal",
+ VerticalValue = "Vertical",
+ };
+
+ var result = converter.Convert(null, typeof(string), null, "en-us");
+ Assert.AreEqual("Vertical", result);
+ }
+
+ [TestCategory("Converters")]
+ [UITestMethod]
+ public void Test_OrientationConvertVerticalToVisibility()
+ {
+ var converter = new OrientationToObjectConverter
+ {
+ HorizontalValue = Visibility.Visible,
+ VerticalValue = Visibility.Collapsed,
+ };
+
+ var result = converter.Convert(Orientation.Vertical, typeof(Visibility), null, "en-us");
+ Assert.AreEqual(Visibility.Collapsed, result);
+ }
+
+ [TestCategory("Converters")]
+ [UITestMethod]
+ public void Test_OrientationConvertHorizontalToVisibility()
+ {
+ var converter = new OrientationToObjectConverter
+ {
+ HorizontalValue = Visibility.Visible,
+ VerticalValue = Visibility.Collapsed,
+ };
+
+ var result = converter.Convert(Orientation.Horizontal, typeof(Visibility), null, "en-us");
+ Assert.AreEqual(Visibility.Visible, result);
+ }
+
+ [TestCategory("Converters")]
+ [UITestMethod]
+ public void Test_OrientationConvertStringToVisibilityWithNegateTrue()
+ {
+ var converter = new OrientationToObjectConverter
+ {
+ HorizontalValue = Visibility.Visible,
+ VerticalValue = Visibility.Collapsed,
+ };
+
+ var result = converter.Convert("anything", typeof(Visibility), "true", "en-us");
+ Assert.AreEqual(Visibility.Visible, result);
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnitTests/UnitTests.UWP/UI/Controls/Test_ContentSizer.cs b/UnitTests/UnitTests.UWP/UI/Controls/Test_ContentSizer.cs
new file mode 100644
index 00000000000..0d9f500ab0f
--- /dev/null
+++ b/UnitTests/UnitTests.UWP/UI/Controls/Test_ContentSizer.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Toolkit.Uwp.UI.Automation.Peers;
+using Microsoft.Toolkit.Uwp.UI.Controls;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
+using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Automation.Peers;
+
+namespace UnitTests.UWP.UI.Controls
+{
+ [TestClass]
+ [TestCategory("Test_ContentSizer")]
+ public class Test_ContentSizer
+ {
+ [UITestMethod]
+ public void ShouldConfigureContentSizerAutomationPeer()
+ {
+ const string automationName = "MyContentSizer";
+ const string name = "ContentSizer";
+
+ var contentSizer = new ContentSizer();
+ var contentSizerAutomationPeer = FrameworkElementAutomationPeer.CreatePeerForElement(contentSizer) as SizerAutomationPeer;
+
+ Assert.IsNotNull(contentSizerAutomationPeer, "Verify that the AutomationPeer is ContentSizerAutomationPeer.");
+
+ contentSizer.Name = name;
+ Assert.IsTrue(contentSizerAutomationPeer.GetName().Contains(name), "Verify that the UIA name contains the given Name of the ContentSizer.");
+
+ contentSizer.SetValue(AutomationProperties.NameProperty, automationName);
+ Assert.IsTrue(contentSizerAutomationPeer.GetName().Contains(automationName), "Verify that the UIA name contains the given AutomationProperties.Name of the ContentSizer.");
+ }
+ }
+}
diff --git a/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj b/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj
index d50b438032e..0cb3c0b4db0 100644
--- a/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj
+++ b/UnitTests/UnitTests.UWP/UnitTests.UWP.csproj
@@ -169,6 +169,7 @@
+
@@ -243,6 +244,7 @@
+