Search code examples
wpfstyleschildwindow

Disable the parent window, without changing the visual appearance of any of the controls


I am trying to solve what looks like a simple problem, but I can’t find a simple solution. I have a window in wpf, that window contains only of one listbox with few names and one button, the button don’t do anything. When you click on an item in the listbox it creates and shows a new window (child window). At this point I want the window behind to be disabled, but I also want the look of it not to change. However the listbox and the button (or any other control I put on that window) change their colour. How do I achieve the above, in the simplest possible way?

Here is the code:

<Window x:Class="MainWindowStyleAndBehaviour.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" WindowState="Maximized" Name="myWindow">
<Grid Background="Green">
    <ListBox Name="myListbox" HorizontalAlignment="Left" VerticalAlignment="Top" Height="200"     Width="300" Background="Red" FontSize="30" SelectionChanged="myListbox_SelectionChanged" Margin="10"/>
    <Button Content="Don't click me" Width="300" Height="60" HorizontalAlignment="Right" VerticalAlignment="Top" FontSize="30" Margin="10"/>
</Grid>
</Window>

 namespace MainWindowStyleAndBehaviour
 {
   public partial class MainWindow : Window
   {
     public MainWindow()
     {
        InitializeComponent();
        Names = new List<string>() { "Sonia", "Bruno", "Cezar" };
        myListbox.ItemsSource = Names;
     }

     public List<string> Names { get; set; }

     private void myListbox_SelectionChanged(object sender, SelectionChangedEventArgs e)
     {
        Window w = new Window();
        myWindow.IsEnabled = false;
        w.Show();
        w.Closed += (s, ea) => myWindow.IsEnabled = true;
     }
  }
}

Thank you in advance :)


Solution

  • You can overlay a grid control over the main window, and make it collapsed to start with. When you open the popup window (called OtherWindow below) make this grid Visible. Because it is on top of all other controls, it will capture all the mouse events, effectively disabling the whole window without changing its appearance.

    MainWindow.xaml.cs

    using System.Windows;
    using System.Windows.Input;
    
    namespace Test
    {
      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
        }
    
        private void listbox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
          utilityGrid.Visibility = System.Windows.Visibility.Visible;    // <- Crux
          OtherWindow otherWindow = new OtherWindow(ReturnToEnabled);
          PreviewKeyDown += MainWindow_PreviewKeyDown;
          otherWindow.Show();
        }
    
        private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
        {
          e.Handled = true;
        }
    
        private void ReturnToEnabled()
        {
          utilityGrid.Visibility = System.Windows.Visibility.Collapsed;
          PreviewKeyDown -= MainWindow_PreviewKeyDown;
        }
      }
    }
    

    MainWindow.xaml

    <Window x:Class="Test.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="200" Width="300" WindowStartupLocation="CenterScreen">
        <Grid  >
          <Grid x:Name="PutYourStuffInHere">
          <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
          <ListBox Grid.Row="0" MouseDoubleClick="listbox_MouseDoubleClick" >
            <ListBoxItem>Double-Click</ListBoxItem>
            <ListBoxItem>Sample</ListBoxItem>
            <ListBoxItem>Text</ListBoxItem>
          </ListBox>
        </Grid>
        <Grid x:Name="utilityGrid" Background="White" Opacity="0.0" Visibility="Collapsed"></Grid>
      </Grid>
    </Window>
    

    OtherWindow.xaml.cs

    using System;
    using System.Windows;
    
    namespace Test
    {
      public partial class OtherWindow : Window
      {
        Action _returnToEnabled;
        public OtherWindow(Action ReturnToEnabled)
        {
          InitializeComponent();
          _returnToEnabled = ReturnToEnabled;
        }
    
        private void buttonClose_Click(object sender, RoutedEventArgs e)
        {
          Close();
        }
    
        private void OtherWindow_Closed(object sender, EventArgs e)
        {
          if (_returnToEnabled != null)
            _returnToEnabled();
        }
      }
    }
    

    OtherWindow.xaml

    <Window x:Class="Test.OtherWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="OtherWindow" Height="300" Width="300" WindowStyle="ToolWindow"
            Closed="OtherWindow_Closed">
        <Grid>
        <Button Width="100" Height="25" x:Name="buttonClose" Click="buttonClose_Click">Close</Button>
        </Grid>
    </Window>