-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Add Expander Events #9555
Add Expander Events #9555
Conversation
You can test this PR using the following package version. |
You can test this PR using the following package version. |
You can test this PR using the following package version. |
RaisePropertyChanged( | ||
IsExpandedProperty, | ||
oldValue: value, | ||
newValue: _isExpanded, | ||
BindingPriority.LocalValue, | ||
isEffectiveValue: true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is kind of code I generally would prefer to avoid, as this API changes the property value without actually setting the value in conventional way.
Although, it also seems to the most convenient way to do these events for the users who would use this control.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tend to agree with you. I made sure to document reasoning well in case there are different suggestions. However, while it looks bad in general, I can't think of any downsides. It should be perfectly harmless. It's just one of those bad special cases.
That said, I did think of a way around this. It requires removing the toggle button entirely from the control template. State would then be managed entirely within the Expander itself -- which is probably a fundamentally better design to begin with. I think WPF was also being lazy and didn't want to duplicate a lot of code, as well.
Im not sure how much code duplication would be required to remove the toggle button from the default template. Pointer press and click would have to be entirely managed by the Expander. Keyboard navigation as well. It would probably be similar to what we did for SplitButton.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave this open and we can always come back and change things in the future. It shouldn't be a bad breaking change except for those writing their own control themes (rare).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably will be less customizable without the toggle button
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works well.
Thank you for continuing improving our controls!
No problem, these type of changes are driven by my own needs though :) It's a pain point in porting that is tricky to work around in some cases. It's less code just to add to the framework. |
You can test this PR using the following package version. |
(I've seen this discussed but can't find where now, apologies if I'm going over old ground...) I'm not sure that reusing EDIT: Ok, found it: #9979 (comment) - yeah I think adding a separate event args class would be a good idea. |
Also given that canceling the expansion is causing problems (#9979) are we sure we want to add that feature? I may be looking at the wrong version but it looks like WinUI doesn't have a way to cancel. |
@grokys I have usages for cancelling the expansion. Specifically, in an accordion-layout not allowing to close the currently opened expander unless another one is expanded first. Other Expander implementations from 3rd party control libraries have supported cancellation in the past as well. I see no fundamental reason we shouldn't have this from an API standpoint -- cancelling is fairly common like this in other cases/controls as well. There are no technical limitations that can't be worked-around either. This and the other PR does work well -- you can try it out in control catalog now -- it just has to force a binding update due to a more general problem (discussed #9979 (comment)). Edit: To summarize I wouldn't say "Canceling the expansion is causing problems". It works just fine already and only needs to work around a fundamental problem with properties. But the work-around is harmless itself. |
Wouldn't it be simpler to just disable the toggle button for the currently expanded expander in that case?
Hmm ok, if you can point me to some examples of this, maybe we can try to work out how they manage this desync between controls. |
It would fundamentally change how the API works. You would have to switch to and add an "AllowExpandCollapse"-type property instead. It is more common (look at Flyout for example) to allow canceling an Opening/Closing type event in XAML frameworks. Microsoft may not have done this a lot but I would argue that's because they never evolved their controls enough before they cancelled the projects. Every subsequent XAML framework has also had less-and-less features so comparing to WinUI/UWP is not always the best either (sorry I'm getting sidetracked).
Well, I think we know the problem here fairly well:
|
What does the pull request do?
Adds four new Expander events:
Additionally, Expanding and Collapsing events can be externally cancelled (marked as handled) to keep the expander in a certain state.
What is the current behavior?
There are no expander events, the IsExpanded property must be observed directly to determine expanded/collapsed state.
What is the updated/expected behavior with this PR?
Four events added as described above.
How was the solution implemented (if it's not obvious)?
Collapsing
/Expanding
events occur syncronously immediately when the IsExpanded property changes.Collapsed
/Expanded
events occur asyncronously after the control state has updated and any content transitions are completed. This is actually the desired implementation in WinUI but was not easy to do there:OnCollapsed(...)
,OnCollapsing(...)
,OnExpanded(...)
,OnExpanding(...)
.Collapsed
is based on WPF: https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.expander.collapsed?view=windowsdesktop-7.0Expanded
is based on WPF: https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.expander.expanded?view=windowsdesktop-7.0Expanding
is based on WinUI: https://learn.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.controls.expander.expanding?view=winui-2.8Collapsing
, not available in either WPF or WinUI, was added for completeness.Expanding
event is intended to be used to dynamically load content before the expander opens.Handled = true
in external event handlersAdditional Resources
Checklist
[ ] Added unit tests (if possible)?Breaking changes
None, except the protected method
protected virtual async void OnIsExpandedChanged(AvaloniaPropertyChangedEventArgs e)
has been removed. The newOnCollapsed(...)
,OnCollapsing(...)
,OnExpanded(...)
,OnExpanding(...)
methods may be used instead.Obsoletions / Deprecations
None
Fixed issues
Closes #9458