MaterialDesignInXAML / MaterialDesignInXamlToolkit

Google's Material Design in XAML & WPF, for C# & VB.Net.
http://materialdesigninxaml.net
MIT License
15.17k stars 3.43k forks source link

Window becomes inactive after DialogHost.Show() #3497

Open Mishin870 opened 7 months ago

Mishin870 commented 7 months ago

Bug explanation

I'm trying to make a preloader using DialogHost (I need to display a loading indicator and lock the application while the data is being loaded)

However, when I call DialogHost.Show(), the application window loses focus

5.0.1-ci571:

https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/assets/12599641/870a9dc8-6a78-467a-923e-92513d43876c

if you click on a dialog, the window will become active again along with the dialog. so they are not mutually exclusive

In my past project I used version 4.6.1 and the window did not lose focus when DialogHost was opened

I tried different versions in the current project:

4.10.0-ci317:

https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/assets/12599641/47933a28-e0f8-4cf1-8cea-f3b8a798802f

How can this be fixed without downgrading to an older version?

My code:

PreloaderDialog

<UserControl x:Class="Client.View.Dialogs.PreloaderDialog"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d">
    <ProgressBar Width="24"
                 Height="24"
                 Margin="16"
                 IsIndeterminate="True"
                 Style="{StaticResource MaterialDesignCircularProgressBar}"
                 Value="33" />
</UserControl>

MainWindow

<Window x:Class="Client.View.Windows.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        xmlns:controls="clr-namespace:Client.View.Controls"
        mc:Ignorable="d"
        Title="FriendSync"
        Height="500" Width="540"
        WindowStartupLocation="CenterScreen">
    <materialDesign:DialogHost
        Identifier="RootDialog"
        DialogTheme="Inherit"
        Loaded="DialogHost_OnInitialized">
        ...
    </materialDesign:DialogHost>
</Window>

Method to show preloader

public static async Task DoWithPreloader(Action action, string host = DIALOG_ROOT) {
  var dialog = new PreloaderDialog();

  if (DialogHost.IsDialogOpen(host)) {
    try {
      DialogHost.Close(host);
    } catch (Exception) {
      // ignored
    }
  }

  await DialogHost.Show(dialog, host, new DialogOpenedEventHandler((_, args) => {
    action();
    try {
      if (!args.Session.IsEnded) {
        args.Session.Close(false);
      }
    } catch (Exception) {
      // ignored
    }
  }));
}

Calling code

DialogUtils.DoWithPreloader(() => {
  // some time-consuming code
});

Version

5.0.1-ci571

MichelMichels commented 7 months ago

Can you provide us a test repository which show cases the problem?

Mishin870 commented 7 months ago

Here are the two minimal projects inside the solution They are identical in everything except the MaterialDesign version

DialogHostTest - v5.0.1-ci588, when clicking on any of the buttons the window title becomes inactive

DowngradedTest - v4.10.0-ci317, the window stays active (which is what I want, it looks nice)

https://github.com/Mishin870/DialogHostTest

MichelMichels commented 7 months ago

I pinpointed the issue these lines of code in DialogHost.cs.

This change was introduced by @Keboo in this commit. @Keboo do you remember why these lines were necessary?

github-actions[bot] commented 6 months ago

This issue is marked stale because it has been open 30 days with no activity. Remove stale label or update the issue, otherwise it will be closed in 14 days.

github-actions[bot] commented 5 months ago

This issue is marked stale because it has been open 30 days with no activity. Remove stale label or update the issue, otherwise it will be closed in 14 days.

diegokalvo commented 4 months ago

Similar issue here. My textbox within dialog UserControl loses focus after DialogHost.Show(). In 4.9.0 it doesn't happen

ashidaharo commented 4 months ago

I’ve read #2912, #3451, and this thread, so I have some understanding of the issue's background. It seems there are two types of dialogs:

  1. Dialogs that require user interaction and are expected to take focus away from the parent when displayed.
  2. Dialogs that are displayed temporarily and are expected to keep the focus on the parent.

To meet these requirements, I believe the best solution is to provide an argument when calling the DialogHost.Show method to determine whether the dialog should take focus or not. Additionally, we could introduce variations of the DialogHost.Show method that explicitly indicate whether the dialog should take focus.

Of course, there is some debate as to which default behavior-whether 1. or 2.-is appropriate for the existing DialogHost.Show method without additional arguments or variations.

@MichelMichels, what do you think about this solution?

MichelMichels commented 4 months ago

@ashidaharo I don't think there is a situation where the DialogHost control doesn't need to take focus. Would you have an example of this?

ashidaharo commented 4 months ago

@MichelMichels Isn't that exactly what @Mishin870 is doing? He displayed a loading indicator using a dialog host. That should have been the start of this thread when it changed to take the focus away from the parent. If the dialog host is not designed to do at least that, then we need something that would do that job well instead of the dialog host.

MichelMichels commented 4 months ago

@ashidaharo I see now. Apologies for any confusion.

What I ment was that (in my opinion) the Window should stay active even when the DialogHost takes focus.

github-actions[bot] commented 3 months ago

This issue is marked stale because it has been open 30 days with no activity. Remove stale label or update the issue, otherwise it will be closed in 14 days.