-
Notifications
You must be signed in to change notification settings - Fork 80
[XAML] Modern Adorners #760
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Original Branch: https://github.com/michael-hawker/Labs-Windows/tree/llama/adorners/labs/Adorners (This was on an older interation of Labs infrastructure, so would make rebasing/updating branch difficult, easier to just start new component and copy over.) Only changes were to modernize atop latest Toolkit packages instead of including copied helper code. Have more updates to build atop this from XAML Studio after, plus some new updates to API surface, and docs for WPF comparisons.
…ass extension for FrameworkElementExtensions
Includes initial support for adorners to adjust to window/content resizing
Co-authored-by: Ahmed <[email protected]> I had missed the warning from CsWinRT, big thanks to @ahmed605 for helping debug this issue in the Windows App Community Discord!
…th `AdornerLayer` and customization point Add extra info about this to the doc TODO: need to test passing in a custom/subclassed Adorner still
TODO: Need to handle the Tab closing (i.e. AdornedElement unloads/disappears should also detach/remove adorner from AdornerLayer)
|
TabView sample is cool, it works great as there's a ScrollViewer within the tabstrip, it's magic. Though removing the tab dynamically leaves the adorner, so definitely adding handling in the new I want to add a custom adorner sample, seeing how hard it'd be to do a resizer sort of helper (akin to the There's a lot of custom Adorner stuff I was looking at in XAML Studio, so I want to pull this in there to test and muck about with how I think this works now and see if it is easy to use... 😅 |
|
I realized that this approach could maybe work for the I've been messing with trying to write a custom adorner sample (Fons also suggested on BlueSky as validation sample: https://bsky.app/profile/fonssonnemans.bsky.social/post/3m6cxed753c2n - that'll be my next one to look at I think), but getting tripped up on them being templated controls, which is a bit tricky. I may also be hitting some C#/WinRT stuff I don't understand... I should try a class-based resource dictionary to see if I can enable x:Bind for ease-of-use... it's unconventional, but may be a great use-case for this scenario. Would make the sample more complex as I don't think I could inline it all (which was getting messy anyways). So, maybe the sample app needs an upgrade to have a |
|
Bug: When I added Unloading support it broke re-appearing on the tab if you move it (need loaded or something?) |
Provide OnAttached/OnDetached helper methods and Typed abstract class
…eed to adjust namespace to match for Sample App to find)
(Should just have this be in the Nuget Package vs. sample...)
|
Now supporting Input Validation... 😅 Super simple to do with the Adorner system now. Added an Adorner which just knows how to interact with
<muxc:NumberBox DataContext="{x:Bind ViewModel}"
Header="Enter your age:"
PlaceholderText="Age"
SpinButtonPlacementMode="Inline"
Value="{x:Bind ViewModel.Age, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ui:AdornerLayer.Xaml>
<local:InputValidationAdorner PropertyName="Age" />
</ui:AdornerLayer.Xaml>
</muxc:NumberBox>Adorner implementation basically:
Thanks to @sonnemaf for the inspiration to put these two scenarios together! 🦙❤️ https://bsky.app/profile/fonssonnemans.bsky.social/post/3m6cxed753c2n |
|
UWP build is failing due to these properties in the samples: But I properly guard them in my XAML: <ResourceDictionary x:Class="AdornersExperiment.Samples.InPlaceTextEditor.InPlaceTextEditorAdornerResources"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Windows11="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 14)"
...
<Popup x:Name="PopupRoot"
Windows11:DesiredPlacement="BottomEdgeAlignedLeft"
Windows11:PlacementTarget="{x:Bind AdornedElement, Mode=OneWay}"What am I missing? @Arlodotexe would this have to do if we're not building with the newer Windows 11 based SDK or something? Thoughts on what I might be missing? |
|
you need to build with 22000 SDK or higher to be able to use these |
|
Thanks for the confirmation @ahmed605, that's what I figured! I'm just a bit confused on why we're not doing that already in our CI/build setup. I'll sync with Arlo on that on Monday. |
This is largely unchanged since 7x, since we haven't had a reason to bump it until now. It should be safe to change with a PR to tooling, our |
…ditional XAML to work
|
Updating with the tooling fix resolves compiling locally. However, I'm getting a weird issue where it says it can't set the |
Note: This sample doesn't work on UWP for some weird issue with Popup.PlacementTarget at runtime, even though it should be supported according to the docs.
…ckage Makes more type-safe and easier to use based on community feedback by placing context on Adorner itself (NotifyDataErrorInfo property) - akin to EditableObject sample change as well. Allows for string collection of validation messages as well as existing ValidationResult behavior. Separate out InputValidationAdorner into its own doc TODO: Issue with form clearing newly corrected fields...
85df605 to
b7637ca
Compare
…rror has been fixed by user Refactored logic into RefreshErrors method to be also used if INotifyDataErrorInfo context or property is dynamically changed as well.
Swap to Border to use more standard resource names/types over the Rectangle we had before (not sure why I had one over the other). This allows for better Background binding, but that doesn't really make a lot of sense in this scenario as it covers control for visibility and input... Note Glyph isn't working for some reason, but maybe we provide a general Severity property on the control and bind that with a SwitchConverter to the InfoBadge...
|
I'm hoping CI will build seems like intermittent issues with workloads for other platforms... then there'll be a nuget package where it can be tested out. FYI @Arlodotexe I think next step is a custom |
Have initial thumbs with cursor changing TODO: Resize...!
Having separate ResizeThumb which handles manipulation is basically a generalized ContentSizer, this helps encapsulate that logic as well nicely. Then the ResizeElementAdorner is just a coordinator/initializer to provide the complete package of resizing. TODO: Moving the element probably can just be handled by the underlying element with standared manipulation (do we have a Behavior for that?) and doesn't need to involve the Adorner layer (outside of syncing movement/position, which needs to be tested...)
…we can update Adorner I'm not sure why the underlying element changed is not triggering the existing Adorner layout hooks, so this'll have to do for now... It at least works as expected now.
|
Added the XAMLAdornerResizeElement.mp4The Adorner itself is pretty simple here just acting as a container, bridge, and overlay. The rest is handled basically by the thumb. |


See discussion for more details: #278
This is my modern Adorners implementation that I started a few years ago, originally here: https://github.com/michael-hawker/Labs-Windows/tree/llama/adorners/labs/Adorners
Since that was in a prior iteration of Labs, I've brought it over atop a new component template base, as well as merging in updates from XAML Studio where I've been using this a bit more already in practical scenarios.
Currently only works for UWP, debugging issue with Windows App SDK... (It used to work here I'm pretty sure, so not sure what's going on, more discussion on Discord: https://discord.com/channels/372137812037730304/672911467401445377/1440605732276801537)- Fixed, thanks @ahmed605!Done:
Adornerbase class/helperInputValidationAdornerto the base package, add some resources for customization and broaden the results it can parse (i.e. just ToString on object if notValidationResult, maybe callback event for parsing collection?)DataContexton base control or just have a property to pass in the VM object on the Adorner itself? (Moved to Adorner itself, makes more strongly typed, much nicer)TODO:
ResizeElementAdorner(biggest test)InputValidationAdornerand revalidation and adorner not clearingOpen Questions (may not be handled in initial PR):
AdornedElementunloadingIsClipEnabled?GetDesiredTransform? (Should we use transform over Canvas coordinates?)Demo video showing animations with an InfoBadge on a TabViewItem:
XAMLAdornerAnimations.mp4
"Squarer" video with data binding:
XAMLAdornerAnimations2.mp4