我正在处理的应用程序使用模态对话框。我目前正在实现会话超时,它会在一定数量的非活动分钟后自动锁定屏幕,但我遇到了一个问题,如果用户打开了一个模态对话框,它将显示在会话锁定屏幕的顶部。
在WPF .Net应用程序中,用于识别和强制关闭任何模态对话框(使用取消操作)的一般逻辑是什么?
发布于 2019-06-13 20:13:51
有一些复杂的模态对话框,这是最好的说明通过实例。下面的处理程序在单击时生成一个新的Window
,然后是一个MessageBox
,等待第二个,然后关闭两者。注意,我们希望MainWindow
保持开放。
public partial class MainWindow : Window
{
const int timeout = 1000;
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var win = new Window { Content = new Label { Content = "Not a modal Window" } };
using (new Timer(OnTimerElapsed, win, timeout, Timeout.Infinite))
{
win.Show();
MessageBox.Show($"Open windows: {Application.Current.Windows.Count}", "Just a sec...");
}
}
private void OnTimerElapsed(object state)
{
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() =>
{
((Window)state).Close();
}));
}
}
这个例子的主要内容是非模态窗口和MessageBox都是关闭的。然而,如果我们仔细看看OnTimerElapsed
,我们会发现只有非模态窗口才被告知关闭。考虑到这是调用MessageBox.Show
时(最后一次)活动的窗口,它也是MessageBox的所有者,因此关闭它也会关闭MessageBox。
我们可以用MessageBox.Show(...);
替换行new OpenFileDialog().ShowDialog();
,得到类似的结果。
这就把我们带到了最高层。如果我们想关闭一个从主窗口实例化的MessageBox,我们如何在不同时关闭这两个窗口的情况下做到这一点呢?一种选择是创建一个虚拟所有者窗口,这个窗口从未显示过,只是充当一个调用Close
的引用。
public partial class MainWindow : Window
{
const int timeout = 1000;
private Window _modalOwner;
public MainWindow()
{
InitializeComponent();
InitializeModalOwner();
}
private void InitializeModalOwner()
{
_modalOwner = new Window
{
AllowsTransparency = true,
ShowInTaskbar = false,
WindowStyle = WindowStyle.None,
Background = Brushes.Transparent
};
_modalOwner.Show();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
using (new Timer(OnTimerElapsed, null, timeout, Timeout.Infinite))
{
MessageBox.Show(_modalOwner, $"Open windows: {Application.Current.Windows.Count}", "Just a sec...");
}
}
private void OnTimerElapsed(object state)
{
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() =>
{
var mainWindow = Application.Current.MainWindow;
foreach (Window win in Application.Current.Windows)
if(win != mainWindow)
win.Close();
InitializeModalOwner();
}));
}
}
在这里,我们迭代当前WindowCollection
中的所有窗口,并关闭它们,只要它们不是应用程序的主窗口。在此之后,_modalOwner
也将被关闭,这使它变得毫无用处--一旦Window
实例关闭,您就不能调用它。这也是再次初始化它的地方。
new OpenFileDialog().ShowDialog(_modalOwner);
也是如此。调用Window
的任何ShowDialog
实例都将自动添加到Application.Current.Windows
集合中。
资源
https://stackoverflow.com/questions/56582844
复制相似问题