microsoft / TemplateStudio

Template Studio accelerates the creation of new WinUI 3, WPF, and UWP apps using a wizard-based experience.
Other
2.71k stars 461 forks source link

Handling ContentDialog winui3 one content dialog at a time #4654

Closed humbertomoli99 closed 1 year ago

humbertomoli99 commented 1 year ago

Is your feature request related to a problem? Please describe.

I was struggling with the administration of the content dialogs open at the same time for winui3 and I made this helper or method and with the help of gpt chat I created a helper.

need to pass XamlRoot to ContentDialog for winui 3

Describe the solution you'd like

I have a code that manages one content dialog at a time for winui3 applications since it can only have one content dialog at a time

I want to contribute to add this helper to the winui3 template studio, here I leave the code, it is a helper, but I have little experience editing template studio, I don't know how to contribute easily but I leave the code here anyway.

This code is a generic class called ContentDialogHelper that acts as a helper for displaying and controlling content dialogs in a C# application. The generic parameter T must be a subclass of ContentDialog, which means that only classes that inherit from ContentDialog can be passed as an argument when using this class.

The ContentDialogHelper class has a single static Instance instance that follows the Singleton design pattern, which means that there can only be one instance of this class in the application. The instance is created the first time it is accessed and is stored in the static variable instance.

The class has a method called ShowContentDialog that displays a content dialog and returns the result of the user's interaction with the dialog. The method takes a dialog object of type T as its argument, which is the dialog to display.

Before displaying the dialog, the method checks if a dialog is already open using the boolean variable isDialogOpen. If a dialog is open, it returns ContentDialogResult.None indicating that no action has been taken on the current dialog.

If there is no dialog open, the dialog is displayed using the ShowAsync() method and waits for the user to interact with it. The result of the user interaction is stored in a result variable of type ContentDialogResult.

If an exception occurs during the execution of the dialog, the dialog is hidden using the Hide() method and the result is set to ContentDialogResult.None.

At the end, the isDialogOpen variable is set to false to indicate that the dialog has been closed.

To call the ShowContentDialog method of the ContentDialogHelper, you must first obtain an instance of the class using the Instance static property, as shown below:

ContentDialogHelper<MyCustomContentDialog> helper = ContentDialogHelper<MyCustomContentDialog>.Instance; You can then call the ShowContentDialog method by passing your dialog object as an argument:

ContentDialogResult result = await helper.ShowContentDialog(myDialog); Where myDialog is an instance of your custom dialog that inherits from ContentDialog. The await method is used to wait for the dialog to close and to get the result of user interaction.

private async void Delete()
    {
        ContentDialog deleteDialog = new()
        {
            Title = "Delete?",
            XamlRoot = XamlRoot ,
            PrimaryButtonText = "Delete",
            SecondaryButtonText = "Cancel",
            DefaultButton = ContentDialogButton.Primary,
            Content = "Are you sure you want to delete?"
        };

        ContentDialogResult dialogResult = await ContentDialogHelper<ContentDialog>.Instance.ShowContentDialog(deleteDialog);
}
public class ContentDialogHelper<T> where T : ContentDialog
{
    private static ContentDialogHelper<T> instance;
    public static ContentDialogHelper<T> Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new ContentDialogHelper<T>();
            }
            return instance;
        }
    }
    private bool isDialogOpen = false;
    public async Task<ContentDialogResult> ShowContentDialog(T dialog)
    {
        if (isDialogOpen)
        {
            return ContentDialogResult.None;
        }

        isDialogOpen = true;
        ContentDialogResult result;
        try
        {
            result = await dialog.ShowAsync();
        }
        catch (Exception)
        {
            dialog.Hide();
            result = ContentDialogResult.None;
        }
        isDialogOpen = false;

        return result;
    }
}

Describe alternatives you've considered

No response

Additional context

No response

Applies to the following platforms:

mrlacey commented 1 year ago

Including miscellaneous helper classes inside Template Studio generated projects is not ideal as it greatly increases the support and maintenance burden of the code and can make it harder to update previously generated projects in the future.

This also seems a fairly trivial wrapper that only prevents issues with trying to display multiple dialogs if they use this helper. What if someone wanted to show multiple dialogs on different roots? What about queueing multiple dialogs so that the next is shown once one is closed? Is this thread safe? Why not use the latest C# language features and appropriate naming conventions?

I'm not looking for or expecting answers to the above; just trying to highlight that there's a lot more to think about here.

Instead, the Comunity Toolkit might be a better place for this. I recommend opening a discussion there to get further feedback.

mikebattista commented 1 year ago

Agreed. Recommend considering for the Community Toolkit.