Comment puis-je déterminer si une fenêtre WPF est modale?
Quel est le moyen le plus simple de savoir si une fenêtre est ouverte modalement ou non?
CLARIFIACTION: J'ouvre une fenêtre appelant
myWindow.ShowDialog();
J'ai un pied de page avec un bouton " OK " et "Annuler" que je veux seulement montrer si la fenêtre est ouverte modalement. Maintenant, je me rends compte que je peux définir une propriété en faisant ceci:
myWindow.IsModal = true;
myWindow.ShowDialog();
Mais je veux la fenêtre, c'est soi-même de faire cette détermination. Je veux vérifier dans l'événement "chargé" de la fenêtre si oui ou non il est modal.
Mise à jour La propriété "IsModal" n'existe pas en fait dans une fenêtre WPF. C'est une propriété que j'ai créé. ShowDialog () bloque le thread courant. Je suppose que je peux déterminer si la fenêtre est ouverte via ShowDialog () en vérifiant si le thread actuel est bloqué. Comment pourrais-je aller sur le faire?
7 réponses
Depuis http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c95f1acb-5dee-4670-b779-b07b06afafff/
"Système.Windows.Interop.ComponentDispatcher.IsThreadModal peut vous dire si le thread appelant exécute actuellement un HWND modal."
Il y a un champ privé _showingAsDialog
chaque fois qu'une fenêtre WPF est une boîte de dialogue modale. Vous pouvez obtenir cette valeur via la réflexion et l'incorporer dans une méthode d'extension:
public static bool IsModal(this Window window)
{
return (bool)typeof(Window).GetField("_showingAsDialog", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(window);
}
La valeur est définie sur true lorsque la fenêtre est affichée en tant que modal (ShowDialog) et définie sur false une fois la fenêtre fermée.
Ok, depuis que ma dernière idée a été rejetée, Je l'ai prouvé. cela fonctionne - et je l'ai testé dans une nouvelle application WPF, donc je sais que cela fonctionne:
Dans l'événement chargé de ma fenêtre principale (Window1), j'ai fait:
Dim frm As New Window2
frm.ShowDialog()
Dans Mon Window2, j'ai ombré la méthode 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
Dans mon événement chargé, j'ai ensuite déclenché une boîte de message pour m'assurer que la propriété IsModal a été changée de False à True et qu'elle me donne True, donc je sais Qu'IsModal a été défini. MyBase.ShowDialog () force alors la base classe à charger en tant que Modal. Shadows nous permet de remplacer le comportement par défaut même si la méthode ShowDialog() n'a pas été déclarée comme pouvant être remplacée.
Bien qu'il ne "détermine pas" lui-même, il ne vous oblige pas à transmettre une valeur booléenne de l'extérieur, et ne vous oblige pas à définir L'IsModal de l'extérieur, il le définit à l'intérieur de lui-même, il est accessible de l'extérieur si vous avez choisi de l'utiliser de cette façon. Il définit la valeur uniquement si elle est chargée en utilisant la méthode ShowDialog () et non si vous utilisez la méthode Show (). Je doute que vous trouverez une méthode beaucoup plus simple de le faire.
Voici un fragment de convertisseur qui est utile pour masquer des éléments lorsque la fenêtre est appelée par la méthode 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;
}
En utilisant L'automatisation de L'interface utilisateur dans Windows, j'ai trouvé quelque chose comme ceci:
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();
}
}
Mais cela ne semble pas fonctionner. Il y a une propriété IsModal http://msdn.microsoft.com/en-us/library/system.windows.automation.provider.iwindowprovider.ismodal.aspx il doit y avoir un moyen approprié d'obtenir AutomationElement pour la fenêtre et de vérifier si la propriété IsModal est vraie via Automation.
Une fenêtre modale arrête le traitement jusqu'à ce qu'elle soit fermée.
Cet exemple montre l'affichage d'une fenêtre non modale
dim f as myWindow
f.show
someOtherMethod()
Dans cet exemple, someOtherMethod s'exécute immédiatement après le lancement de la fenêtre.
Cet exemple montre l'affichage d'un modal:
dim f as myWindow
f.showDialog
someOtherMethod()
Dans cet exemple, someOtherMethod() ne s'exécutera pas tant que la méthode ShowDialog ne sera pas retournée (ce qui signifie que la fenêtre modale a été fermée)
Modifier en raison d'une clarification: Remplacez le ShowDialog et passez dans un booléen.
dim f as MyWindow
f.ShowDialog(true)
, Puis dans la fenêtre
Public Function Shadows ShowDialog(myVar as boolean) As Boolean
if myVar then ShowButtons()
return mybase.ShowDialog()
End Function
Serait-il possible de vérifier le parent de la fenêtre pour voir si elle est désactivée? Je ne suis pas sûr si cela peut être fait via des API WPF ou non, mais si rien d'autre, vous pouvez obtenir le HWND de la fenêtre WPF, obtenir son parent via Win32 P/Invoke (ou autre), puis vérifier s'il est désactivé ou non.
Certainement pas une méthode propre, mais il semble que cela pourrait fonctionner.