2009-03-03 8 views
51

J'ai une application WPF avec ces trois types de choses ...WPF: Comment définir la fenêtre Propriétaire d'une boîte de dialogue affichée par un UserControl?

  • WindowMain
  • UserControlZack
  • WindowModal

UserControlZack1 se trouve sur mon WindowMain ...

UserControlZack1 affiche une boîte de dialogue de fenêtre WindowModal ...
<Window x:Class="WindowMain" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:ProjectName" 
     ... 
     Name="WindowMain"> 
    <Grid> 
     ... 
     <local:UserControlZack x:Name="UserControlZack1" ... /> 
     ... 
    </Grid> 
</Window> 

Comment puis-je définir box.Owner à la bonne fenêtre, mon instance en cours d'exécution de WindowMain?

Je ne peux pas utiliser box.Owner = Me.Owner, car "'Propriétaire' n'est pas membre de 'ProjectName.UserControlZack'." Je ne peux pas utiliser box.Owner = Me.Parent, car cela renvoie une grille, pas la fenêtre.

Je ne peux pas utiliser box.Owner = WindowMain, car "'WindowMain' est un type et ne peut pas être utilisé comme une expression."

+1

Une réponse correcte et acceptable a probablement déjà été envoyée. Basé uniquement sur les votes, Martin devrait probablement être accepté. – Emyr

Répondre

0

Je l'ai à travailler en rampant tout le chemin à travers mon XAML ...

 
box.Owner = DirectCast(DirectCast(DirectCast(Me.Parent, Grid).Parent, Grid).Parent, Window) 

Mais cela semble tout à fait inélégant. Y a-t-il un meilleur moyen?

+0

Voir ci-dessous sur l'utilisation d'un RoutedUICommand qui je pense est la manière la plus élégante. Toutes mes excuses pour le C#, je ne suis pas un gars VB! –

0

Que diriez-vous de changer le nom de la fenêtre à WindowMain1 ou quelque chose, et en définissant le propriétaire à cela?

+0

"Nom 'WindowMain1' n'est pas déclaré." –

+0

Ah, je vois, n'a pas assez lu la question, vous le faites à l'intérieur de la classe de contrôle utilisateur plutôt que la classe de formulaire principal – Davy8

5

Mise à jour pour essayer d'aider Greg à partir des commentaires. La commande fonctionne dans le menu principal de Windows, le bouton dans le contrôle utilisateur et le menu contextuel dans le contrôle utilisateur.

Je le ferais avec des commandes. Donc, avoir une classe Commands.cs quelque chose comme:

public static class Commands 
{ 
    public static RoutedUICommand TestShowDialogCommand = new RoutedUICommand("Test command", "TestShowDialog", typeof(Commands)); 
} 

enregistrer ces dans la fenêtre principale: (vous n'avez pas besoin canshow valeur par défaut true)

public Window1() 
    { 
     InitializeComponent(); 

     CommandManager.RegisterClassCommandBinding(typeof(System.Windows.Controls.Control), 
      new CommandBinding(Commands.TestShowDialogCommand, ShowDialogCommand, CanShowDialogCommand)); 
    } 

    private void ShowDialogCommand(object sender, ExecutedRoutedEventArgs e) 
    { 
     var box = new Window(); 
     box.Owner = this; 
     box.ShowDialog(); 

    } 

    private void CanShowDialogCommand(object sender, CanExecuteRoutedEventArgs e) 
    { 
     e.CanExecute = true; 
    } 

Ceci est mon XAML pour la fenêtre principale:

<Window x:Class="WpfApplication1.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:WpfApplication1="clr-namespace:WpfApplication1" 
Title="Window1" Height="300" Width="322"> 
<Grid> 
    <StackPanel> 
     <Menu> 
      <MenuItem Header="Test"> 
       <MenuItem Header="ShowDialog" Command="{x:Static WpfApplication1:Commands.TestShowDialogCommand}"/> 
      </MenuItem> 
     </Menu> 
     <WpfApplication1:BazUserControl /> 
    </StackPanel> 
</Grid> 
</Window> 

C'est le XAML pour mon contrôle utilisateur (code par défaut derrière seulement)

<UserControl x:Class="WpfApplication1.BazUserControl" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:WpfApplication1="clr-namespace:WpfApplication1" 
Height="300" Width="300"> 
<Grid> 
    <StackPanel> 
     <Button Command="{x:Static WpfApplication1:Commands.TestShowDialogCommand}" Content="ClickMe" ></Button> 
     <TextBox> 
      <TextBox.ContextMenu> 
       <ContextMenu> 
        <MenuItem Header="ShowDialog" Command="{x:Static WpfApplication1:Commands.TestShowDialogCommand}" /> 
       </ContextMenu> 
      </TextBox.ContextMenu> 
     </TextBox> 
    </StackPanel> 
</Grid> 
</UserControl> 

Vous pourriez aller un peu plus loin et gérer la commande dans une classe de contrôleur à la place et rendre ce bit plus MVC.

+0

Lorsque j'utilise cette technique, l'événement CanExecute n'est pas appelé pour la référence de la UserControl. CanExecute semble être par défaut à false, désactivant l'élément sur lequel la commande est activée (un menuitem de contexte, dans mon cas). Un MenuItem dans la fenêtre parente n'a aucun problème et est activé. –

+0

Cela a quelque chose à voir avec le routage des commandes. Mon UserControl n'obtient pas le focus, mais possède un menu contextuel. Si aucun élément n'est sélectionné/concentré lorsque j'essaie d'afficher le menu contextuel de UserControl, l'événement de commande n'est pas routé. –

+0

Si vous voulez poster plus d'informations dans une question, je verrai si je peux vous aider. J'utilise des commandes dans toute l'application WPF que je réalise, et je les aime vraiment pour le moment. –

37

Pour obtenir la fenêtre de haut niveau de votre contrôle est, en supposant qu'il existe un:

(Window)PresentationSource.FromVisual(this).RootVisual 

Pour obtenir la fenêtre principale:

Application.Current.MainWindow 
+2

Application.Current.MainWindow m'a donné exactement ce dont j'avais besoin. J'ai besoin d'accéder aux contrôles dans la fenêtre parent à partir d'une fenêtre enfant ouverte en utilisant ShowDialog(). –

112

Essayez d'utiliser

.Owner = Window.GetWindow(this) 
+3

Fonctionne très bien, merci. Et c'est aussi exactement la réponse à cette question :-). –

8
MyWpfDialog dialog = new MyWpfDialog(); 

//remember, this is WinForms UserControl and its Handle property is 
//actually IntPtr containing Win32 HWND. 

new System.Windows.Interop.WindowInteropHelper(dialog).Owner = this.Handle; 

dialog.ShowDialog(); 
+0

méfiez-vous avec celui-ci. J'ai eu des problèmes étranges lors de l'exécution dans 'VMWare Fusion' sur un' Macintosh' - la fenêtre est apparue pendant une seconde puis disparue. – itsho

+0

Heads up: si vous avez une autre fenêtre (Splash window, etc.) affichée - vous devrez ** définir ** le 'Owner' pour cela aussi! sinon vous aurez des comportements étranges - votre fenêtre principale n'obtiendra pas l'événement 'OnActivated'/restera en arrière-plan/disparaîtra soudainement, etc. – itsho

Questions connexes