[WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口
[WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口
周银辉
现象:
大家可以试试下面这个很有趣但会带来Defect的现象:当我们将子窗口按照ShowDialog()的方式显示出来的时候,很明显该窗口是模式化的(即主窗口等待该窗口的返回,主窗口将不相应用户输入),但如果此时将子窗口的Visibility设置成Visibility.Hidden来隐藏窗口,然后再将Visibility设置成Visibility.Visible来再次显示子窗口,此后子窗口便是非模式的了(即主窗口和子窗口一样相应用户输入)
案例:
当用户不操作软件达到一定的时间间隔后,软件会隐藏该软件当前显示的所有窗口,并弹出“锁定窗口”,当用户手动解锁后,“锁定窗口”隐藏,其它所有窗口重新显示出来。
对于上述案例中的窗口,如果使用设置Visibility的方式来显示或隐藏窗口,如果被隐藏的窗口是模式对话框的化,便会在重新显示时出现上述问题。
解决方案:
可以用一个相对简单的方式来解决这个问题:“隐藏” 就是 "看不见”, “把窗口扔到显示屏幕之外”就是“看不见”。(这属于“WO,KAO"类的方案,而非”WOW,SAI“,不过却能很好地工作。”写软件就是骗入“----用高科技骗人的眼睛、耳朵,写游戏就更得会骗人了)
代码:
public class WindowVisibilityHelper : DependencyObject
{
public static bool GetIsVisible(DependencyObject obj)
{
return (bool)obj.GetValue(IsVisibleProperty);
}
public static void SetIsVisible(DependencyObject obj, bool value)
{
obj.SetValue(IsVisibleProperty, value);
}
public static readonly DependencyProperty IsVisibleProperty =
DependencyProperty.RegisterAttached("IsVisible", typeof(bool),
typeof(WindowVisibilityHelper),
new PropertyMetadata(true, IsVisiblePropertyChangedCallback));
private static void IsVisiblePropertyChangedCallback(DependencyObject obj,
DependencyPropertyChangedEventArgs e)
{
var window = (Window)obj;
var visible = (bool)e.NewValue;
if (!visible)
{
SetWindowState(window, window.WindowState);
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
}
SetWindowLocation(window, new Point(window.Left, window.Top));
window.Left = -100000;
window.Top = -100000;
SetWindowIsShowInTaskBar(window, window.ShowInTaskbar);
window.ShowInTaskbar = false;
}
else
{
window.WindowState = GetWindowState(window);
Point loc = GetWindowLocation(window);
window.Left = loc.X;
window.Top = loc.Y;
window.ShowInTaskbar = GetWindowIsShowInTaskBar(window);
window.Activate();
window.BringIntoView();
}
}
private static Point GetWindowLocation(DependencyObject obj)
{
return (Point)obj.GetValue(WindowLocationProperty);
}
private static void SetWindowLocation(DependencyObject obj, Point value)
{
obj.SetValue(WindowLocationProperty, value);
}
private static readonly DependencyProperty WindowLocationProperty =
DependencyProperty.RegisterAttached("WindowLocation", typeof(Point),
typeof(WindowVisibilityHelper), new UIPropertyMetadata(new Point()));
private static WindowState GetWindowState(DependencyObject obj)
{
return (WindowState)obj.GetValue(WindowStateProperty);
}
private static void SetWindowState(DependencyObject obj, WindowState value)
{
obj.SetValue(WindowStateProperty, value);
}
private static readonly DependencyProperty WindowStateProperty =
DependencyProperty.RegisterAttached("WindowState", typeof(WindowState),
typeof(WindowVisibilityHelper), new UIPropertyMetadata(WindowState.Normal));
private static bool GetWindowIsShowInTaskBar(DependencyObject obj)
{
return (bool)obj.GetValue(WindowIsShowInTaskBarProperty);
}
private static void SetWindowIsShowInTaskBar(DependencyObject obj, bool value)
{
obj.SetValue(WindowIsShowInTaskBarProperty, value);
}
private static readonly DependencyProperty WindowIsShowInTaskBarProperty =
DependencyProperty.RegisterAttached("WindowIsShowInTaskBar", typeof(bool),
typeof(WindowVisibilityHelper), new UIPropertyMetadata(true));
}
{
public static bool GetIsVisible(DependencyObject obj)
{
return (bool)obj.GetValue(IsVisibleProperty);
}
public static void SetIsVisible(DependencyObject obj, bool value)
{
obj.SetValue(IsVisibleProperty, value);
}
public static readonly DependencyProperty IsVisibleProperty =
DependencyProperty.RegisterAttached("IsVisible", typeof(bool),
typeof(WindowVisibilityHelper),
new PropertyMetadata(true, IsVisiblePropertyChangedCallback));
private static void IsVisiblePropertyChangedCallback(DependencyObject obj,
DependencyPropertyChangedEventArgs e)
{
var window = (Window)obj;
var visible = (bool)e.NewValue;
if (!visible)
{
SetWindowState(window, window.WindowState);
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
}
SetWindowLocation(window, new Point(window.Left, window.Top));
window.Left = -100000;
window.Top = -100000;
SetWindowIsShowInTaskBar(window, window.ShowInTaskbar);
window.ShowInTaskbar = false;
}
else
{
window.WindowState = GetWindowState(window);
Point loc = GetWindowLocation(window);
window.Left = loc.X;
window.Top = loc.Y;
window.ShowInTaskbar = GetWindowIsShowInTaskBar(window);
window.Activate();
window.BringIntoView();
}
}
private static Point GetWindowLocation(DependencyObject obj)
{
return (Point)obj.GetValue(WindowLocationProperty);
}
private static void SetWindowLocation(DependencyObject obj, Point value)
{
obj.SetValue(WindowLocationProperty, value);
}
private static readonly DependencyProperty WindowLocationProperty =
DependencyProperty.RegisterAttached("WindowLocation", typeof(Point),
typeof(WindowVisibilityHelper), new UIPropertyMetadata(new Point()));
private static WindowState GetWindowState(DependencyObject obj)
{
return (WindowState)obj.GetValue(WindowStateProperty);
}
private static void SetWindowState(DependencyObject obj, WindowState value)
{
obj.SetValue(WindowStateProperty, value);
}
private static readonly DependencyProperty WindowStateProperty =
DependencyProperty.RegisterAttached("WindowState", typeof(WindowState),
typeof(WindowVisibilityHelper), new UIPropertyMetadata(WindowState.Normal));
private static bool GetWindowIsShowInTaskBar(DependencyObject obj)
{
return (bool)obj.GetValue(WindowIsShowInTaskBarProperty);
}
private static void SetWindowIsShowInTaskBar(DependencyObject obj, bool value)
{
obj.SetValue(WindowIsShowInTaskBarProperty, value);
}
private static readonly DependencyProperty WindowIsShowInTaskBarProperty =
DependencyProperty.RegisterAttached("WindowIsShowInTaskBar", typeof(bool),
typeof(WindowVisibilityHelper), new UIPropertyMetadata(true));
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?