Ответ 1
От http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c95f1acb-5dee-4670-b779-b07b06afafff/
"System.Windows.Interop.ComponentDispatcher.IsThreadModal может сказать вам, есть ли в вызывающем потоке текущий модальный hwnd."
Какой самый простой способ выяснить, открывается ли окно модально или нет?
ПОЯСНЕНИЯ:
Я открываю окно вызова
myWindow.ShowDialog();
У меня есть нижний колонтитул с кнопками "ОК" и "Отмена", которые я хочу показать, только если окно открыто модально. Теперь я понимаю, что могу установить свойство, выполнив это:
myWindow.IsModal = true;
myWindow.ShowDialog();
Но я хочу, чтобы само окно приняло такое решение. Я хочу проверить в событии Loaded
окна, является ли оно модальным.
ОБНОВИТЬ
Свойство IsModal
фактически не существует в окне WPF. Это свойство, которое я создал. ShowDialog()
блокирует текущий поток.
Я предполагаю, что могу определить, открывается ли окно с помощью ShowDialog()
, проверяя, заблокирован ли текущий поток. Как бы я поступил так?
От http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c95f1acb-5dee-4670-b779-b07b06afafff/
"System.Windows.Interop.ComponentDispatcher.IsThreadModal может сказать вам, есть ли в вызывающем потоке текущий модальный hwnd."
Там частное поле _showingAsDialog
, когда окно WPF является модальным диалогом. Вы можете получить это значение через отражение и включить его в метод расширения:
public static bool IsModal(this Window window)
{
return (bool)typeof(Window).GetField("_showingAsDialog", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(window);
}
Значение устанавливается равным true, когда окно отображается как модальное (ShowDialog) и устанавливается на false после закрытия окна.
Хорошо, так как моя последняя идея проголосовала, я доказал это. это работает - и я тестировал его в новом приложении WPF, поэтому я знаю, что он работает:
В моем основном окне (Window1) Loaded event я сделал:
Dim frm As New Window2
frm.ShowDialog()
В моем Window2 я затенял метод ShowDialog()
Private _IsModal As Boolean = False 'This will be changed in the IsModal method
Public Property IsModal() As Boolean
Get
Return _IsModal
End Get
Set(ByVal value As Boolean)
_IsModal = value
End Set
End Property
Public Shadows Sub ShowDialog()
IsModal = True
MyBase.ShowDialog()
End Sub
В моем загруженном событии я затем уволил окно сообщения, чтобы убедиться, что свойство IsModal изменено с False на True, и оно дает мне True, поэтому я знаю, что IsModal установлен. Затем MyBase.ShowDialog() заставляет базовый класс загружаться как модальный. Shadows позволяет нам переопределить поведение по умолчанию, даже если метод ShowDialog() не был объявлен как переопределяемый.
Пока он не "самостоятельно определяется", он не требует, чтобы вы передавали любое логическое значение извне и не требовали, чтобы вы устанавливали IsModal извне, он устанавливает его внутри себя, он доступен извне если вы так решили использовать его таким образом. Он устанавливает значение только в том случае, если оно загружено с помощью метода ShowDialog(), а не при использовании метода Show(). Я сомневаюсь, что вы найдете гораздо более простой способ сделать это.
Вот фрагмент конвертера, который полезен для скрытия элементов, когда окно вызывается методом ShowDialog:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Window window = value as Window;
if (window != null)
{
var showingAsDialogFieldInfo = typeof(System.Windows.Window).GetField("_showingAsDialog",
BindingFlags.NonPublic | BindingFlags.Instance);
if ((bool) showingAsDialogFieldInfo.GetValue(window) == false)
{
return Visibility.Visible;
}
}
return Visibility.Hidden;
}
модальное окно перестанет обрабатываться до тех пор, пока оно не будет закрыто.
В этом примере показано отображение немодального окна
dim f as myWindow
f.show
someOtherMethod()
В этом примере someOtherMethod запускается сразу после запуска окна.
В этом примере показано отображение модального:
dim f as myWindow
f.showDialog
someOtherMethod()
В этом примере someOtherMethod() не будет работать до тех пор, пока не вернется метод ShowDialog (это означает, что модальное окно было закрыто)
ИЗМЕНИТЬ из-за уточнения: Переопределите ShowDialog и перейдите в логическое.
dim f as MyWindow
f.ShowDialog(true)
затем в окне
Public Function Shadows ShowDialog(myVar as boolean) As Boolean
if myVar then ShowButtons()
return mybase.ShowDialog()
End Function
Используя UI Automation в Windows, я придумал что-то вроде этого:
void Window2_Loaded(object sender, RoutedEventArgs e)
{
var hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
var el = AutomationElement.FromHandle(hwnd);
Object oPattern = null;
if (el.TryGetCurrentPattern(WindowPattern.Pattern, out oPattern))
{
var pattern = oPattern as WindowPattern;
this.Title = pattern.Current.IsModal.ToString();
}
}
Но это кажется неработоспособным. Существует свойство IsModal http://msdn.microsoft.com/en-us/library/system.windows.automation.provider.iwindowprovider.ismodal.aspx должен быть правильный способ получить AutomationElement для окна и проверить, является ли его свойство IsModal истинным через Автоматизация.
Вы также можете создать новый класс Dialog, который наследуется от Window. Создайте приватную переменную IsDialog в классе Dialog и переопределите функцию ShowDialog, используя new. Установите для переменной IsDialog значение true, когда вызывается ShowDialog:
public class Dialog : Window
{
private bool IsDialog;
new public bool? ShowDialog()
{
IsDialog = true;
return base.ShowDialog();
}
}
Можно ли проверить родительское окно окна, чтобы узнать, отключен ли он? Я не уверен, что это можно сделать с помощью API-интерфейсов WPF или нет, но если вы еще ничего не получили HWND из окна WPF, получите его родителя через Win32 P/Invoke (или что-то еще), а затем проверьте, отключен или нет.
Определенно не чистый метод, но кажется, что он может работать.
Window не позволяет вам установить значение для Window.DialogResult, если окно не было открыто с помощью ShowDialog(). Следовательно, вы можете попытаться установить Window.DialogResult и посмотреть, генерирует ли он исключение.