Microsoft-ui-xaml: Proposal: Default button concept

Created on 22 Jun 2019  ·  13Comments  ·  Source: microsoft/microsoft-ui-xaml

Proposal: Default button concept

Add support for setting the default button to WinUI, allowing users to invoke it by pressing enter on another field.

Summary

Every windowing framework I've ever used, from VB3, has had the concept of a default button which is invoked by pressing enter when focused on other form fields (for example, a text box). This is analogous to AcceptButton in WinForms and IsDefault in WPF.

WinUI should have the ability to set a default button so that pressing enter can invoke the action without needing to trap the key down event to look for enter being pressed.

Update 28/6 - I think it should be possible to also set a cancel button in the same manner. I have updated the rationale and scope accordingly.

Rationale

  • Makes this easier for developers and more consistent with other windowing frameworks
  • Less boiler-plate code to write
  • Users are able to use their keyboard for navigation (escape and enter) as they have for many years on Windows and other platforms.

Scope


| Capability | Priority |
| :---------- | :------- |
| Pressing enter will invoke the default button | Must |
| Pressing escape will invoke the cancel button | Must |
| The default button should be visually distinguishable from other buttons |Should |
| Assign different default / cancel buttons for different controls or control sections (similar to how x:DefaultBindMode works) | Could |

area-Commanding feature proposal team-Controls

Most helpful comment

@YuliKl

(again, the cancel behavior is already built into ContentDialog),

I have a content dialog with a AutoSuggestBox, and when it's focused the Enter/Escape shortcut don't work (even though I would like them to). There seems to be no easy way to programmatically trigger primary click or cancellation (see here for a potential solution), is it something that could be exposed in the dialog control?

All 13 comments

@knightmeister, would you say that a default button is applicable only to forms scenarios? Or are there other types of pages where this would be helpful?

Xaml does provide this default button experience within ContentDialog, but we don't currently have a stand-alone default button.

buttons

All the buttons from the various Microsoft frameworks include at least two button styles. Usually the accent colour one is used for this, but there is also an outlined button that could be used to allow it to be further distinguished.

@knightmeister, would you say that a default button is applicable only to forms scenarios? Or are there other types of pages where this would be helpful?

My initial response was to say Forms, but thinking about it there are situations where there are multiple buttons (such as a switchboard) where the user might want to have a default starting button where there are no other form fields present.

Please note I'm just about to amend the initial proposal to include Cancel button, I think that these concepts are used together. While we don't presently have modal dialog support (see #885) if we have the ability to use proper windows, it becomes more relevant.

@knightmeister (and also @mrlacey, @dragocubed, @Poopooracoocoo who have liked this proposal) - I'm still struggling to understand the scenarios when app developers would use this.

  • Default button - I'm aware of a "submit button on a form" scenario. Are there others?
  • Switchboard - @knightmeister, what do you mean by that? Can you point me to an app or show a screenshot?
  • Cancel button - that feels like a dialog scenario (and is already supported by ContentDialog). Does this also apply to forms? If so, what's the expected behavior? (Clear the form fields? Navigate back to the previous page on the backstack by closing the form page? Raise a Cancel event for the app to handle? Something else?)

@mdtauk, thank you for the controls compilation. Xaml's generic.xaml already includes the AccentButtonStyle resource which is leveraged by ContentDialog and can be used by apps to draw a visually consistent button. AccentButtonStyle does not provide the "press Enter anywhere to invoke this button" behavior.

Hi @YuliKl

Regarding your points above:

  1. Default button - you've summed it up. One thing I'd point out is that it should be possible to set a default button hierarchically, if possible. For example, buttons in one stack panel may have a different default button to those in another stack panel.

  2. With respect to "Switchboards". This is very common in LOB apps and Access in particular has this concept. Something like this:

image

  1. IMHO, the app should be able to trap an event or supply a command if it's not mapped to a button. I think that if you tie the cancel action to a predefined course of action (i.e. go back, clear fields, etc) that's going to be too limiting. The developer can programatically chose the most appropriate course of action.

So its more than a default style for a button, or even a design for destructive and confirmatory button command - but a behavioural thing.

Is this something that gets added to Content Dialog, to set a default button?
Would this be a property for the Page element to select an initial control focus?

Then if it is a "default" property on every control or every button control, how would it handle having it set on multiple controls?

I was only thinking about forms, or steps in a wizard where 'Next' is the default until reaching the last step when it becomes 'Complete' (or equivalent)

As far as I remember, WinForms and WPF handle the ability to specify defaults differently.
On WinForms, there is a page/window level property that can be used to define the default button.
On WPF, buttons have an IsDefault property and the last one to set it becomes the default.

My preference is to have WinUI reflect the WPF model because:

  • It improves parity between WinUI and WPF as they have more similar concepts to start with as the are both XAML based.
  • It doesn't require assigning names to buttons just to be able to reference them elsewhere in the same XAML file. (This approach would avoid needing to name a button if it was never needed to be changed dynamically.)
  • It could be easier to set a default button on arbitrary controls (such as a custom popup) rather than only being available in whatever object has a the DefaultButton property. (I'm not sure how this would work in practice though--sorry, I haven't thought through all the details here yet.)
  • It could be easier to set a default button on arbitrary controls (such as a custom popup) rather than only being available in whatever object has a the DefaultButton property. (I'm not sure how this would work in practice though--sorry, I haven't thought through all the details here yet.)

In a flyout like TeachingTip, or dialogs, that default would become the default action on Enter. In a form you would suppose it would be the only thing on the page that could be a default.

Outside of those scopes, I guess the last default would be the one picked.

Does the Page XAML object need a "default listener" to keep track of the default? Dialogs and flyouts would need to be able to set this default when they are either modal or the light dismiss focus right?

  • It could be easier to set a default button on arbitrary controls (such as a custom popup) rather than only being available in whatever object has a the DefaultButton property. (I'm not sure how this would work in practice though--sorry, I haven't thought through all the details here yet.)

In a flyout like TeachingTip, or dialogs, that default would become the default action on Enter. In a form you would suppose it would be the only thing on the page that could be a default.

Outside of those scopes, I guess the last default would be the one picked.

Does the Page XAML object need a "default listener" to keep track of the default? Dialogs and flyouts would need to be able to set this default when they are either modal or the light dismiss focus right?

The implications I hadn't thought through were what happens with a custom popup which is still part of the same page (rather than a dialog which has it's own context) when the popup is dismissed. This should (re)set any previous default.
This is the only scenario I can think of where something would need to know what the default was before. Is this what you meant by "default listener"?
For the most part I'd expect it to work by setting an AccessKey (or equivalent) on the button.

Another thought about this proposal:

Would it only work on Button or could it also work with HyperlinkButton?

I'd like to see HyperlinkButton supported (so can have purely text based buttons get this functionality without retemplating) but don't think it's appropriate to add it to ButtonBase as there are things that inherit from it for which this does not make sense (such as CheckBox.)

This is the only scenario I can think of where something would need to know what the default was before. Is this what you meant by "default listener"?

Pretty much yea. There should be a way to override the default contextually, as in ContentDialog or TeachingTip, etc. For as long as the dialog or control has the "focus", it's default would override any others. When it is dismissed, the default returns to what it was previously.

Thank you for helping me understand this proposal. While apps can already implement this behavior today, it requires a good amount of custom code. (ContentDialog is a notable exception, the control has had a DefaultButton since Windows 1703.)

We won't be able to prioritize this work for a while, but this definitely feels useful. I'm less convinced about the cancel button requirement (again, the cancel behavior is already built into ContentDialog), but the default button feels like a convenient time savings.

We'll revisit this proposal after WinUI 3.

@YuliKl

(again, the cancel behavior is already built into ContentDialog),

I have a content dialog with a AutoSuggestBox, and when it's focused the Enter/Escape shortcut don't work (even though I would like them to). There seems to be no easy way to programmatically trigger primary click or cancellation (see here for a potential solution), is it something that could be exposed in the dialog control?

Was this page helpful?
0 / 5 - 0 ratings