WindowsCommunityToolkit
WindowsCommunityToolkit copied to clipboard
๐ง SizerBase class for GridSplitter + new ContentSizer and PropertySizer components
Fixes #2976 #2017 #3949
The end goal of this PR is to have a base component which both ContentSizer and GridSplitter inherit from. It will also simplify the GridSplitter component to not have a sub-component for controlling the mouse-cursor behavior and instead use our mouse cursor extensions. This should resolve #2017. This also allows us to properly implement GridSplitter cursor behavior for WinUI 3 as it should be owned by the component itself and we can just use ProtectedCursor
instead of our cursor extensions.
The end goal is that GridSplitter will be functionally equivalent to the one within the toolkit, though technically from a component/style standpoint this is a breaking change for 8.0. Updating should be straight-forward unless using some properties we've removed/changed around style/cursors which have been moved to the XAML template.
Overview of new SizerBase class
This PR introduces a new base class SizerBase
(name to be finalized) which centralizes the logic for 'splitter/sizer/gripper' type controls like GridSplitter
. The base class handles the following:
- Shared XAML Template
- Simplified
Cursor
handling using our Mouse extension (also one line change for WinUI 3 when we port forProtectedCursor
) - ๐ Created
OrientationToObjectConverter
to handle character change based on Orientation - Set automation name via XAML (to be tested still)
- Simplified
- Mouse Interaction (๐ fixed long-standing bug #3949 from v1.1 of original GridSplitter; manipulation done cumulatively vs. delta now.)
- Keyboard Interaction
- Accessibility
- Common Properties/Behaviors
- DragIncrement/KeyboardIncrement (๐ brought forward from WPF GridSplitter, now on base class)
-
RightToLeft
flow handling (๐ fixed for keyboard, unknown bug) - Orientation
- Abstract methods for manipulation:
- OnLoaded
- OnDragStarting
- OnDragHorizontal
- OnDragVertical
- Shared VSM (๐ now supports
IsEnabled
states and aligns toThumb
states)
The subclasses like GridSplitter
then only need to implement the abstract methods provided OnLoaded
, OnDragStarting
, OnDragHorizontal
, and OnDragVertical
to apply the requested movement amount to the element being manipulated, e.g. a Grid
. This makes the sub-class controls very simple and flexible and easier to follow logic-wise.
New Controls: ContentSizer and PropertySizer
On top of this new refined base class, we introduce two new controls:
- The
ContentSizer
control is a more flexible/generic version of ourGridSplitter
control. It provides a bar which can then control the size of anyTarget
element. This can be used to make more complex UIs and things like collapsible trays with theExpander
control. It's actually the component I use to remember the Sidebar position within XAML Studio. - The
PropertySizer
control is even more generalize and a little more niche, but allows the manipulation of anydouble
property via aTwoWay
binding to that property (either another UI Element or even a ViewModel). This makes it super simple for example to manipulate aNavigationView
'sOpenPaneLength
property to create a customized sidebar experience for NavigationView with no further modifications, this is the sample provided in our sample app. This addresses https://github.com/microsoft/microsoft-ui-xaml/issues/190.
PR Type
What kind of change does this PR introduce?
- Bugfix
- Feature
- Refactoring (no functional changes, no api changes)
- Build or CI related changes (ui testing)
What is the current behavior?
Grid Splitter is a complex component made of a separate piece which controls mouse cursor behavior. It is also restricted for use within a Grid.
What is the new behavior?
Grid Splitter is now based off a new base class which provides the look-and-feel and mouse behavior with our mouse extensions API. A new ContentSizer and PropertySizer also inherit from this base to provide a more generalized solution for other types of UI scenarios.
Note: The underlying logic for how GridSplitter works with a Grid
has been left unchanged in this PR (for the most part - outside of updating it to use Cumulative values vs. deltas basically). If we want to adopt the WPF logic specifically, I suggest we do that afterwards as a separate PR, though note the bug note below as well. We can open an issue later.
PR Checklist
Please check if your PR fulfills the following requirements:
- [ ] Tested code with current supported SDKs
- [ ] Pull Request has been submitted to the documentation repository instructions. Link:
- [x] Sample in sample app has been added / updated (for bug fixes / features)
- [ ] Icon has been created (if new sample) following the Thumbnail Style Guide and templates
- [ ] New major technical changes in the toolkit have or will be added to the Wiki e.g. build changes, source generators, testing infrastructure, sample creation changes, etc...
- [ ] Tests for the changes have been added (for bug fixes / features) (if applicable)
- [x] Header has been added to all new source files (run build/UpdateHeaders.bat)
- [ ] Contains NO breaking changes
List of Work to be Done
- [x] Migrate ContentSizer into Toolkit
- [x] Add infrastructure to support GridSplitter tests within the UI Test integration harness
- [x] Investigate
TargetControl
loading issues? - Haven't noticed with latest incarnations of components with shared base class. - [x] Need to be more specific about Direction/Sizing for ContentSizer (i.e. it only works Left/Top currently, not Right/Bottom)
- [x] Investigate if can auto-detect alignment from TargetControl and/or
- [x] Have property for movement direction
- [x] Setup proper gripper character based on direction
- [x] Setup common base class (
SizerBar
,SplitterBar
,SlidingBar
,HandleBar
?) so can be used for GridSplitter - [x] Refactor ContentSizer on common base class
- [x] Refactor GridSplitter on common base class
- [x] Remove extra GripperHoverWrapper and use MouseExtensions (like ContentSizer)
- [ ] Once working with existing code, investigate if we want to migrate WPF logic in another PR
- [ ] Extra Bug from WPF: if grid splitter is to the right on the right-most column it can't re-size it...
- [ ] Need to test Narrator/AutomationProperty & Test AutomationPeer
- [ ] Update Design projects for VS Metadata for Designer
- [ ] Check if
Cursor
property can be provided as a custom one without interference - [ ] Add new UI Tests for new controls
- [ ] Modernize template style: rounded corners? accent color? etc...
- [ ] Do we need an easier way to customize content/template (style is pretty simple)?
- [ ] Docs
- [ ] Do we want to name things as
GripperBarBase
,ContentGripperBar
, andPropertyGripperBar
instead? (GridSplitter
is a polyfill so remains the same.) Or some other naming scheme?
Any suggestions on the name for the common base component?
Thanks michael-hawker for opening a Pull Request! The reviewers will test the PR and highlight if there is any conflict or changes required. If the PR is approved we will proceed to merge the pull request ๐
Ugh forgot to add headers, will fix in a min
Filed #4500, looks like there's an underlying issue with our CI at the moment. I built this locally with no issues before pushing up.
Moved this over to labs for now, so this may just get closed out and we'll re-import later for 8.0 via labs restructure/future work there.
This is now an experiment in Toolkit Labs (see #4487 for info on Labs).
It can be found at the following Experiment: https://github.com/CommunityToolkit/Labs-Windows/issues/101
Closing this PR out now as we'll re-integrate from Labs later for 8.0.