AvaloniaUtils / DialogHost.Avalonia

AvaloniaUI control that provides a simple way to display a dialog with information or prompt the user when information is needed
MIT License
228 stars 15 forks source link

Can it be used purely from code-behind? #21

Closed mysteryx93 closed 1 year ago

mysteryx93 commented 1 year ago

I'm exploring to include support for DialogHost in MvvmDialogs. What I'm seeing is that you designed it to already support MVVM but in a different way.

Can it still be used purely from code-behind, to integrate into MvvmDialogs architecture?

What I'll want is to fill in this code.

public async Task<object?> ShowDialogHostAsync<T>(Control? owner)
    where T : Control, new()
{
    return await DialogHost.Show(new T());
}

How do I set the owner?

I could have a standard method to display any UserControl, then extensions methods calling it like MessageBox and InputText that display preset UserControls. If I pass the UserControl instance, then I can also set initial properties. Does that structure make sense?

Edit: I think I'm getting somewhere with this. Then I just need to create UserControls for the dialogs and it should work?

public async Task<object?> ShowDialogHostAsync<T>(Control? owner, T content, DialogClosingEventHandler? closingHandler = null)
    where T : Control
{
    var host = owner?.FindDescendantOfType<DialogHost>()!;
    closingHandler ??= (_, _) => { };
    return await DialogHost.Show(content, host, closingHandler);
}
SKProCH commented 1 year ago

Hello, @mysteryx93

Yep, actually this should work fine. I think it's not even always necessary to create a UserControl for the content, because it can be resolved through a DataTemplates or ViewLocator, for example.

If you still have some questions - feel free to ask

mysteryx93 commented 1 year ago

I'm scratching my head as to the best way to implement that.

If I want to provide default MessageBox Views, what's the best way to make them customizable? Either defined as Control with StyleSheet that needs to be imported manually (not ideal), pass a UserControl directly that contains code-behind logic, or pass a ViewModel that links to a default View that can be customized (more in-line with the MVVM theme).

Remains the issue of how the app will recognize the default View location by default in spite of custom app naming conventions, and how to override the default one...

Then the design might as well work with FluentAvalonia.ContentDialog too. This one has no default View resolving AFAIK so either way I need to resolve the View myself. And might as well also support ModernWpf and make it a standard MvvmDialogs platform-independent feature.

What are the differences between FluentAvalonia.ContentDialog and DialogHost.Avalonia?

Also, it is annoying to have to define it in every View.

<dialogHost:DialogHost CloseOnClickAway="True">
    <dialogHost:DialogHost.DialogContent>
        <!-- put your dialog content here-->
    </dialogHost:DialogHost.DialogContent>
    <!-- put the content over which the dialog is shown here (e.g. your main window grid)-->
</dialogHost:DialogHost>

Perhaps I could try "injecting" it at runtime, removing the Window content and re-adding it into the newly-added DialogHost? Why does it need to be put in the View to begin with? Other implementations do not require it.

mysteryx93 commented 1 year ago

ok the other implementations are WinUI's ContentDialog that includes Title and Buttons, whereas yours is only pure Content. Trying to share the API is probably not a good idea.

SKProCH commented 1 year ago

As solution for customizing - i think what you simple can pass the object to DialogHost, and everything was handled internally.
If it is a Control - it will be displayed. If it is a VM or something - will be lookup for DataTemplates (and ViewLocator in App.axaml in the final).

As for "define in every view" - yes. This act like any other control that have content (grid, button, etc). This made for allow users to have multiple DialogHosts in one window and have non full-windowed dialog host, e.g.: image

Perhaps I could try "injecting" it at runtime, removing the Window content and re-adding it into the newly-added DialogHost?

Yep, if you need to provide dialogs out of the box for window - it can be nice way, i think.

As for the title and buttons - i think what window dialogs (MessageBox'es and simular) should have this because of Windows concepts of windows in OS). But DialogHost is more generic thing. Actually no one can prohibit to create a dialog with only ProgressBar, without buttons and any other content. So, if you implementation rely on buttons i think what you should add you custom view with it. You can add your custom VM to View mapping to DialogHost.DataTemplates itself, too,

mysteryx93 commented 1 year ago

Alright I've done the implementation. Only problem is the other bug I reported.

A "default" MessageBox implementation would be an issue... linking the library ViewModels and Views, being able to override, etc. If I don't do MessageBoxes, then all those problems are non-issues.

Truth be told, the reason someone would use this over ContentDialog is to have more flexibility; and with more flexibility, they won't need "default" MessageBoxes anyway. Those who use the manual customization of DialogHost will implement their own dialogs.