Display and Results
Once the User Prompt Content and User Prompt Buttons have been defined, it is time to show the prompt and collect feedback from the user.
Display Mode
When using the builder pattern, the following options are available for displaying a user prompt (as defined by UserPromptDisplayMode):
Value | Description |
---|---|
Dialog | On supported platforms, the prompt is hosted in a Window and shown as a dialog. Using this mode on unsupported platforms will throw PlatformNotSupportedException . |
Overlay | The prompt is hosted on an overlay that is displayed over the owning TopLevel (e.g., Window or browser view). |
DialogPreferred | Dialog will be used on supported platforms; otherwise, Overlay will be used where dialogs are not supported. (Default) |
The DialogPreferred mode is the default, but the static UserPromptBuilder.DefaultDisplayMode property can be used to change the default to a different value.
The UserPromptBuilder.WithDisplayMode method can be used to configure the RequestedDisplayMode of an individual builder instance to a non-default value.
Warning
Requesting Dialog mode on unsupported platforms will throw PlatformNotSupportedException
. Generally, DialogPreferred should be requested instead.
The actual display mode used may differ from the display mode requested! For example, if an existing user prompt is currently displayed as an overlay, additional user prompts will also display as an overlay even if dialogs are supported and requested. Before the prompt is shown, the ActualDisplayMode property will be set to either Dialog or Overlay based on the display mode being used.
Showing a User Prompt Dialog
The builder pattern is recommended for showing user prompts, but is not required. On supported platforms, a user prompt is typically displayed as a modal dialog. The UserPromptWindow.ShowDialog method can be used to display any UserPromptControl in a modal dialog that will automatically close and return a MessageBoxResult when the user responds.
The following code demonstrates showing a UserPromptControl as a modal dialog using UserPromptWindow and evaluating the result:
var userPromptControl = new UserPromptControl() {
Content = "This file has been modified. Do you want to save your changes before closing?",
StandardButtons = MessageBoxButtons.YesNo,
};
var result = await UserPromptWindow.ShowDialog(userPromptControl, "Save Changes?");
if (result == MessageBoxResult.Yes) {
// Insert code to save changes here
}
When using the builder pattern, the Show method is used to display a prompt based on the configuration and return the result as shown in the sample blow:
var result = await UserPromptBuilder.Configure()
.WithContent("This file has been modified. Do you want to save your changes before closing?")
.WithStandardButtons(MessageBoxButtons.YesNo)
.Show();
if (result == MessageBoxResult.Yes) {
// Insert code to save changes here
}
Warning
The return value of UserPromptWindow.ShowDialog and UserPromptBuilder.Show is a Task<MessageBoxResult>
that must be awaited to prevent the calling thread from proceeding before the user responds. Attempting to read the Task.Result
without awaiting its completion can result in thread deadlock.
Note
See the "Configuring and Evaluating Results" section below for more details on working with the result of a prompt.
Title
All Window
instances should have a title, so the UserPromptWindow.ShowDialog method optionally accepts an argument that will be used as the title of the UserPromptWindow when displayed.
When using the builder pattern, the WithTitle method is used to set the title associated with the user prompt:
await UserPromptBuilder.Configure()
// ... other configuration options here
.WithTitle("Actipro Avalonia Controls")
.Show();
Overlay Title Mode
When using the builder pattern and displaying a prompt as an Overlay, the following modes are available for displaying titles (as defined by UserPromptOverlayTitleMode):
Value | Description |
---|---|
AlwaysHide | The overlay title is always hidden, even when UserPromptBuilder.Title is configured. |
AlwaysShow | The overlay title is always shown. |
ShowWhenNoHeader | An overlay title is only shown when UserPromptControl.Header is not defined since a header and title are typically redundant. (Default) |
The ShowWhenNoHeader mode is the default, but the static UserPromptBuilder.DefaultOverlayTitleMode property can be used to change the default to a different value.
The UserPromptBuilder.WithOverlayTitleMode method can be used to configure the OverlayTitleMode of an individual builder instance to a non-default value.
Inferred and Fallback Titles
When a title is undefined or null
, the UserPromptControl.StandardStatusIcon property is used to infer a contextually appropriate title. For example, the title is set to "Warning"
when the status icon is MessageBoxImage.Warning.
If a title cannot be inferred, the static UserPromptBuilder.FallbackTitle value will be used.
If a title is still undefined, the TitleAttribute
metadata of the entry assembly will be used.
Tip
See the Localization topic for details on how to customize the string resources used for inferred titles.
Close Caption Button
A UserPromptWindow will only display a Close caption button in the title bar if a response can be associated with closing the window. The CloseResult property is used to define the result associated with closing the window instead of invoking an available button. When set to MessageBoxResult.None, the Close caption button will not be displayed.
When CloseResult is set to null
and the StandardButtons property is used to define the available buttons, an appropriate MessageBoxResult will be assigned to CloseResult based on the current value of StandardButtons.
For example, using MessageBoxButtons.YesNoCancel will automatically assign MessageBoxButtons.Cancel as the CloseResult. Explicitly set the CloseResult to MessageBoxResult.None to prevent the Close caption button from automatically displaying.
When using the builder pattern, the WithCloseResult method is used to set the close result:
await UserPromptBuilder.Configure()
// ... other configuration options here
.WithCloseResult(MessageBoxResult.Ignore)
.Show();
Configuring and Evaluating Results
The UserPromptControl.Result property is used to read or write the user's response to a prompt and is typically only used when working with custom buttons.
The UserPromptWindow.ShowDialog method returns a Task
that, once completed, will return the UserPromptControl.Result. If the UserPromptWindow is closed without invoking one of the available buttons, the value of UserPromptControl.CloseResult is used instead.
The UserPromptControl.Responding event is raised when the UserPromptControl.Result property is changed. UserPromptWindow listens to this event to know when to close the dialog.
When using the builder pattern, the Show method behaves the same as UserPromptWindow.ShowDialog.
Warning
The various Show
and ShowDialog
methods return a Task<MessageBoxResult>
that must be awaited to prevent the calling thread from proceeding before the user responds. Attempting to read the Task.Result
without awaiting its completion can result in thread deadlock.
The following example demonstrates the correct way to evaluate the result:
var result = await UserPromptBuilder.Configure()
// ... other configuration options here
.Show();
Default Button
Typically, the first available button will be the default button that receives initial focus. There are two ways to change this behavior to explicitly indicate which button should be the default: UserPromptControl.DefaultResult and Button.IsDefault
.
When standard buttons are configured using the StandardButtons property, the default button is defined by setting the DefaultResult property to the MessageBoxResult that corresponds to the standard button.
When custom buttons are configured using the ButtonItems property, the first Button
control whose IsDefault
property is set to true
will be configured as the default.
When using the builder pattern, the button builder's UseAsDefaultResult method is used to configure Button.IsDefault
as true
.
await UserPromptBuilder.Configure()
// ... other configuration options here
.WithButton(_ => _
.WithResult(MessageBoxResult.Yes)
.UseAsDefaultResult()
)
.Show();
Tip
Custom buttons can also use the UserPromptControl.DefaultResult property to define the default button if the desired Button
has set the UserPromptControl.ButtonResult
attached property to a MessageBoxResult .
Warning
The UserPromptControl.DefaultResult property is ignored if any button has set Button.IsDefault
to true
.
Responding Event
The UserPromptControl.Responding event is raised when the UserPromptControl.Result property is changed. UserPromptWindow listens to this event to know when to close the dialog.
When using the builder pattern, the OnResponding method is used to define a callback that will receive the UserPromptBuilder and UserPromptResponseEventArgs of the event. The following demonstrates how the callback can be used to cancel a response:
await UserPromptBuilder.Configure()
// ... other configuration options here
.OnResponding((builder, args) => {
if ((builder?.Instance is UserPromptControl userPromptControl) && (userPromptControl.IsChecked)) {
// Cancel the response
args.Cancel = true;
}
})
.Show();
Warning
The Responding event handler or OnResponding callback must be executed synchronously so the thread will be blocked waiting for the response. Otherwise, the prompt will close before the event/callback has completed executing.
Owner
When the user prompt is shown as a modal dialog, it must have an owner Window
. Some of the UserPromptWindow.ShowDialog overloads allow an owner to be specified. If one is not specified, a default owner Window
will be determined by the currently active Window
.
When using the builder pattern, the WithOwner method is used to assign a non-default owner. Since the builder pattern supports displaying dialogs or overlays, the owner is specified as a TopLevel
(which, on desktop applications, is typically a Window
).
Startup Location
By default, a UserPromptWindow.WindowStartupLocation
is set to CenterScreen
, but this can be changed.
The UserPromptWindow.ShowDialog method accepts a callback that can be used to configure the UserPromptWindow before it is displayed. The following sample demonstrates changing the startup location to CenterOwner
:
var userPromptControl = new UserPromptControl() { ... };
Window owner = null; // Use default
await UserPromptWindow.ShowDialog(
userPromptControl,
"Window Title",
owner,
window => {
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
});
See the "Customize UserPromptWindow" section of the Customizing Appearance topic for more examples of how to set properties like WindowStartupLocation
on the UserPromptWindow.
When using the builder pattern, the WithWindowStartupLocation method is used to specify a desired startup location.
await UserPromptBuilder.Configure()
// ... other configuration options here
.WithWindowStartupLocation(WindowStartupLocation.CenterOwner)
.Show();
Tip
When using the builder pattern with auto-sizing, prompts that can be sized within the bounds of their owner Window
will be configured with WindowStartupLocation.CenterOwner
and only larger prompts will default to WindowStartupLocation.CenterScreen
. This dynamic centering, which is the default behavior, is only available if an explicit startup location is not specified.
See the "Auto-Sizing" section below for more details.
Auto-Sizing
Auto-sizing is a feature only available when using the builder pattern. By default, this feature is only enabled when a String
is used as the Content
of the prompt, but the WithAutoSize method can be used to explicitly enable the functionality for non-String
content as well.
Auto-sizing involves a series of calculations that attempt to generate the ideal width of the prompt. The goal is to start at a given width and then ensure the prompt does not exceed a relative height. If the prompt is too tall, the width is increased in logical steps until the height is within a desired range.
The minimum width, accessible by AutoSizeMinimumWidth, is assigned using one of the available arguments passed to the WithAutoSize method.
When UserPromptBuilder.WindowStartupLocation is null
(the default), the auto-size logic will first attempt to size the prompt to a width and height that do not exceed the bounds of the owner. This is important to allow WindowStartupLocation.CenterOwner
to be used without some parts of the prompt potentially displayed off screen. Otherwise, if it is not displayed as an overlay, the prompt will be sized within the working area of the screen so that WindowStartupLocation.CenterScreen
can be used to fully display the prompt.
Tip
Auto-size logic is also applied to MessageBox since it uses the builder pattern to create prompts. This mean that, by default, MessageBox.Show will always attempt to center messages over the owner, but will fall back to center screen if the message is too big.