現象:
大家可以試試下面這個很有趣但會帶來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));
}