2009-03-03 11 views
51

Tengo una aplicación de WPF con estos tres tipos de cosas ...WPF: ¿Cómo configuro la ventana de propietario de un cuadro de diálogo que muestra un UserControl?

  • WindowMain
  • UserControlZack
  • WindowModal

UserControlZack1 se sienta en mi WindowMain ...

<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> 

UserControlZack1 muestra un cuadro de dalog de WindowModal ...

 
Partial Public Class UserControlZack 

    ... 

    Private Sub SomeButton_Click(...) 
     'instantiate the dialog box and open modally... 
     Dim box As WindowModal = New WindowModal() 
     box.Owner = ????? 
     box.ShowDialog() 
     'process data entered by user if dialog box is accepted... 
     If (box.DialogResult.GetValueOrDefault = True) Then 
      _SomeVar = box.SomeVar 
      ... 
     End If 
    End Sub 

End Class 

¿Cómo configuro box.Owner para la ventana correcta, la instancia de WindowMain en ejecución?

No puedo usar box.Owner = Me.Owner, porque "'Owner' no es miembro de 'ProjectName.UserControlZack'."

No puedo usar box.Owner = Me.Parent, porque eso devuelve una Cuadrícula, no la Ventana.

No puedo usar box.Owner = WindowMain, porque "'WindowMain' es un tipo y no se puede usar como una expresión."

+1

Probablemente ya se haya enviado una respuesta correcta y aceptable. Basado únicamente en los votos, Martin probablemente debería ser aceptado. – Emyr

Respuesta

0

lo tengo para trabajar mediante el rastreo de todo el camino de vuelta a través de mi XAML ...

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

Pero esto parece bastante poco elegante. ¿Hay una mejor manera?

+0

Consulte a continuación el uso de RoutedUICommand, que creo que es la forma más elegante. Disculpas por el C#, ¡no soy un tipo VB! –

0

¿Qué hay de cambiar el nombre de la ventana a WindowMain1 o algo así, y configurar el propietario a eso?

+0

"Nombre 'WindowMain1' no está declarado." –

+0

Ah, ya veo, no leí la pregunta con cuidado, estás haciendo esto dentro de la clase de control del usuario en lugar de la clase de formulario principal – Davy8

5

Actualizando para tratar de ayudar a Greg con los comentarios. El comando funciona en el menú de la ventana principal, el botón en el control del usuario y el menú contextual en el control del usuario.

Lo haría con comandos. Así que tener una clase Commands.cs algo como:

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

registrar estos en su ventana principal: (no es necesario el canshow el valor predeterminado es cierto)

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; 
    } 

Ésta es mi XAML para el ventana principal:

<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> 

Este es el XAML para mi control de usuario (código por defecto sólo por detrás)

<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> 

Puede llevarlo un poco más lejos y manejar el comando en una clase de controlador en su lugar y hacerlo un poco más MVC.

+0

Cuando uso esta técnica, el evento CanExecute no se llama para la referencia del Control de usuario. CanExecute parece predeterminado a falso, deshabilitando el elemento en el que está el comando (un elemento de menú contextual, en mi caso). Un MenuItem en la ventana primaria no tiene problemas y está habilitado. –

+0

Tiene algo que ver con el enrutamiento de comandos. Mi UserControl no se enfoca, pero tiene un menú contextual. Si no se selecciona/enfoca ningún elemento cuando trato de ver el menú contextual del UserControl, el evento del comando no se enruta. –

+0

Si desea publicar más información en una pregunta, veré si puedo ayudarlo. Uso comandos en toda la aplicación de WPF que estoy creando, y realmente los amo en este momento. –

37

para obtener la ventana de nivel superior de su control está en, suponiendo que hay una:

(Window)PresentationSource.FromVisual(this).RootVisual 

para obtener la ventana principal:

Application.Current.MainWindow 
+2

Application.Current.MainWindow me dio exactamente lo que necesitaba. Necesito acceder a los controles en la ventana principal desde una ventana secundaria abierta usando ShowDialog(). –

112

intenta utilizar

.Owner = Window.GetWindow(this) 
+3

Funciona muy bien, gracias. Y también es exactamente la respuesta a esta pregunta :-). –

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

tenga cuidado con este. Tuve problemas extraños al ejecutar 'VMWare Fusion' en un' Macintosh': la ventana apareció durante un segundo y luego desapareció. – itsho

+0

Heads up: si tiene otra ventana (ventana de Splash, etc.) mostrada, ¡** debe ** configurar ** 'Propietario' también! de lo contrario, obtendrás comportamientos raros: tu ventana principal no tendrá el evento 'OnActivated'/permanecerá en segundo plano/desaparecerá repentinamente, etc. – itsho

Cuestiones relacionadas