question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Generic Dialogs API spec

See original GitHub issue

I’ve had a couple requests for enhancements to the existing ContentDialog functionality. As a result, I’m drafting up an API spec for generic dialogs. As ContentDialog is a WinUI item (reverse engineered instead of ported, but still) I don’t want to modify the API in a way that makes it different to the upstream version other than bug fixes or minor feature additions.

The biggest issue from the comments is that the lack of button options in ContentDialog make it somewhat limiting, something the old vista-style TaskDialog solves (to an extent). This proposal, therefore, seeks a new control and API spec. Note that this is just an API spec to layout the general thought and get feedback of desired features - and is not yet a firm proposal or commitment.

EDIT: Final spec laid out here - PR created

public class TaskDialog : ContentControl
{
    /// <summary>
        /// Gets or sets the title of the dialog
        /// </summary>
        /// <remarks>
        /// This is the window caption of the dialog displayed in the title bar. For platforms 
        /// where windowing is not supported, this property has no effect.
        /// </remarks>
        public string Title { get; set; }

        /// <summary>
        /// Gets or sets the dialog header text
        /// </summary>
        public string Header { get; set; }

        /// <summary>
        /// Gets or sets the dialog sub header text
        /// </summary>
        public string SubHeader { get; set; }

        /// <summary>
        /// Gets or sets the dialog Icon
        /// </summary>
        public IconSource IconSource { get; set; }

        /// <summary>
        /// Gets the list of buttons that display at the bottom of the TaskDialog
        /// </summary>
        public IList<TaskDialogButton> Buttons { get; set; }

        /// <summary>
        /// Gets the list of Commands displayed in the TaskDialog
        /// </summary>
        public IList<TaskDialogCommand> Commands { get; set; }

        /// <summary>
        /// Gets or sets the visibility of the Footer area
        /// </summary>
        public TaskDialogFooterVisibility FooterVisibility  { get; set; }

        /// <summary>
        /// Gets or sets whether the footer is visible
        /// </summary>
        public bool IsFooterExpanded { get; set; }

        /// <summary>
        /// Gets or sets the footer content
        /// </summary>
        public object Footer { get; set; }

        /// <summary>
        /// Gets or sets the IDataTemplate for the footer content
        /// </summary>
        public IDataTemplate FooterTemplate { get; set; }

        /// <summary>
        /// Gets or sets whether this TaskDialog shows a progress bar
        /// </summary>
        public bool ShowProgressBar { get; set; }

        /// <summary>
        /// Gets or sets the root visual that should host this dialog
        /// </summary>
        /// <remarks>
        /// For TaskDialogs declared in Xaml, this is automatically set. If you declare a 
        /// TaskDialog in C#, you MUST set this property before showing the dialog to prevent
        /// and error. For desktop platforms, set it to the Window that should own the dialog.
        /// For others, set it to the root TopLevel.
        /// </remarks>
        public IVisual XamlRoot { get; set; }

        /// <summary>
        /// Raised when the TaskDialog is beginning to open, but is not yet visible
        /// </summary>
        public event TypedEventHandler<TaskDialog, EventArgs> Opening;

        /// <summary>
        /// Raised when the TaskDialog is opened and ready to be shown on screen
        /// </summary>
        public event TypedEventHandler<TaskDialog, EventArgs> Opened;

        /// <summary>
        /// Raised when the TaskDialog is beginning to close
        /// </summary>
        public event TypedEventHandler<TaskDialog, TaskDialogClosingEventArgs> Closing;

        /// <summary>
        /// Raised when the TaskDialog is closed
        /// </summary>
        public event TypedEventHandler<TaskDialog, EventArgs> Closed;



        /// <summary>
        /// Shows the TaskDialog
        /// </summary>
        /// <param name="showHosted">Optional parameter that specifies whether this dialog should show in the OverlayLayer even on windowing platforms. Defaults to false</param>
        /// <returns>The TaskDialog result corresponding to the command/button used to close the dialog</returns>
        /// <remarks>
        /// Before calling this method, you MUST set <see cref="XamlRoot"/> property to the TopLevel/Window that should
        /// own or host this Dialog. If you declare the dialog in Xaml, this is done automatically since 
        /// the dialog is already attached to the visual tree
        /// </remarks>
        public async Task<object> ShowAsync(bool showHosted = false) { }

        /// <summary>
        /// Hides the TaskDialog with a <see cref="TaskDialogStandardResult.None"/> result
        /// </summary>
        public void Hide() { }

        /// <summary>
        /// Hides the dialog with the specified dialog result
        /// </summary>
        public void Hide(object result) { }
}

public enum TaskDialogFooterVisibility
{
    Never, // Footer is never visible
    Auto, // Footer title is visible with expand option to show/hide
    Always // Footer is always visible and the footer title is hidden
}

// Base class for controls that can be added to a TaskDialog
// These would be abstractions and not actual controls, TaskDialog would create/manage that
public abstract class TaskDialogControl
{
    public TaskDialogControl() { }

    public TaskDialogControl(string text, object result) { }

    // The text caption of the control
    public string Text { get; set; }

    // The result the button corresponds to and is returned when the dialog
    // closes. Can be TaskDialogStandardResult or an user chosen object
    // May not be null
    public object DialogResult { get; set; }

    // Gets/sets whether the control is enabled
    public bool IsEnabled { get; set; }

    // Is this the default button - will only be settable on one control
    // error thrown if multiple are set
    public bool IsDefault { get; set; }
}

// Represents a regular button in a TaskDialog, can be placed in Buttons or
// Options area of dialog
// Buttons placed in the Buttons area will trigger an automatic close of the dialog,
// Buttons placed in the Options area will not, call Hide() if you wish to do so
public class TaskDialogButton : TaskDialogControl
{
    public TaskDialogButton() { }

    public TaskDialogButton(string text, object result)
        :base(text, result) { }
   
    // An optional icon
    public IconSource IconSource { get; set; }

        /// <summary>
        /// Gets or sets the command that is invoked when the button is clicked
        /// </summary>
        public ICommand Command { get; set; }

        /// <summary>
        /// Gets or sets the command parameter for the <see cref="Command"/>
        /// </summary>
        public object CommandParameter { get; set; }
            
    // Event fired when button is clicked/tapped (occurs before dialog close)
    public event TypedEventHandler<TaskDialogButton, EventArgs> Click;

    // Default Buttons - these will be immutable (no properties / event handlers / commands can be set on them)
    public static readonly TaskDialogButton OKButton = new TaskDialogButton("OK", TaskDialogStandardResult.OK);
    public static readonly TaskDialogButton CancelButton = new TaskDialogButton("Cancel", TaskDialogStandardResult.Close);
    public static readonly TaskDialogButton YesButton = new TaskDialogButton("Yes", TaskDialogStandardResult.Yes);
    public static readonly TaskDialogButton NoButton = new TaskDialogButton("No", TaskDialogStandardResult.No);
    public static readonly TaskDialogButton RetryButton = new TaskDialogButton("Retry", TaskDialogStandardResult.Retry);
    public static readonly TaskDialogButton CloseButton = new TaskDialogButton("Close", TaskDialogStandardResult.Close);
}

// Set of standard results you can use
public enum TaskDialogStandardResult
{
    None,
    OK,
    Cancel,
    Yes,
    No,
    Retry,
    Close
}

// Represents a extra options command - can only be placed in the options area
public class TaskDialogCommand : TaskDialogButton
{
    // Additional caption for this command button
    public string Description { get; set; }

        /// <summary>
        /// Gets or sets whether invoking this command should also close the dialog
        /// </summary>
        public bool ClosesOnInvoked { get; set; }
}

// Represents an radiobutton within a TaskDialog - can only be placed in options area
public class TaskDialogRadioButton : TaskDialogCommand
{
    public bool? IsChecked { get; set; }
}

public class TaskDialogCheckBox : TaskDialogRadioButton
{
}

Final design: image

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:5
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
robloocommented, Feb 17, 2022
1reaction
robloocommented, Feb 17, 2022

FYI, similar ideas were discussed in WinUI here: https://github.com/microsoft/microsoft-ui-xaml/issues/2313. You might find some inspiration/good-ideas there as well.

Read more comments on GitHub >

github_iconTop Results From Across the Web

GenericDialog (ImageJ API)
Creates a new GenericDialog with the specified title. Uses the current image image window as the parent frame or the ImageJ frame if...
Read more >
Dialog (JavaFX 8)
The Dialog class has a single generic type, R, which is used to represent the type of the result property (and also, how...
Read more >
Uses of Package org.eclipse.ui.dialogs
Provides a generic debugger user interface that clients may customize via standard workbench extension points. org.eclipse.ui. Application programming ...
Read more >
Dialog
Quickly bring your app to life with less code, using a modern declarative approach to UI, and the simplicity of Kotlin. ... Start...
Read more >
OpenAPI Specification v3.1.0 | Introduction, Definitions, & ...
The OpenAPI Specification (OAS) defines a standard, programming language-agnostic interface description for HTTP APIs.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found