2009-03-03 4 views
51

Ho un applicazione WPF con questi tre tipi di cose ...WPF: Come si imposta la finestra Proprietario di una finestra mostrata da un controllo utente?

  • WindowMain
  • UserControlZack
  • WindowModal

UserControlZack1 siede sul mio 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 visualizza un box dailog 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 

Come si imposta box.Owner sulla finestra corretta, la mia istanza in esecuzione di WindowMain?

Non riesco a utilizzare box.Owner = Me.Owner, perché "Proprietario" non è un membro di "ProjectName.UserControlZack". "

Non riesco a utilizzare box.Owner = Me.Parent perché restituisce una griglia, non la finestra.

Non riesco a utilizzare box.Owner = WindowMain, perché "'WindowMain' è un tipo e non può essere utilizzato come espressione."

+1

Probabilmente è stata presentata una risposta corretta e accettabile. Basandosi esclusivamente sui voti, probabilmente Martin dovrebbe essere accettato. – Emyr

risposta

0

ho preso a lavorare strisciando tutta la strada attraverso la mia XAML ...

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

ma questo sembra abbastanza poco elegante. C'è un modo migliore?

+0

Vedi sotto sull'uso di RoutedUICommand che ritengo sia il modo più elegante. Mi scuso per il C#, non sono un ragazzo VB! –

0

Che dire cambiare il nome della finestra in WindowMain1 o qualcosa del genere e impostare il proprietario su questo?

+0

"Nome 'WindowMain1' non è dichiarato." –

+0

Ah, vedo, non ho letto abbastanza attentamente la domanda, lo stai facendo all'interno della classe di controllo utente piuttosto che nella classe principale del modulo – Davy8

5

Aggiornamento per provare e aiutare Greg dai commenti. Il comando funziona nel menu principale di Windows, il pulsante nel controllo utente e il menu di scelta rapida nel controllo utente.

Lo farei con i comandi. Quindi avere una classe Commands.cs qualcosa come:

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

registrare questi nella finestra principale: (non è necessario il canshow il valore predefinito è vero)

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

Questo è il mio XAML per la finestra 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> 

Questo è il codice XAML per il mio controllo utente (codice predefinito dietro solo)

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

Si potrebbe prendere un po 'oltre e gestire il comando in una classe controller invece di renderlo un po' più MVC.

+0

Quando utilizzo questa tecnica, l'evento CanExecute non viene chiamato per il riferimento dal UserControl. CanExecute sembra essere impostato su false, disabilitando l'elemento su cui si trova il comando (un menu di scelta rapida, nel mio caso). Un MenuItem nella finestra padre non ha problemi ed è abilitato. –

+0

Ha qualcosa a che fare con il routing dei comandi. My UserControl non ottiene il focus, ma ha un menu contestuale. Se nessun elemento è selezionato/focalizzato quando provo a visualizzare il menu di scelta rapida di UserControl, l'evento comando non viene instradato. –

+0

Se vuoi pubblicare più informazioni in una domanda, vedrò se posso aiutarti. Io uso i comandi attraverso l'app WPF che sto creando e li sto davvero amando al momento. –

37

Per ottenere la finestra di livello superiore il controllo è in, presumere che v'è una sola:

(Window)PresentationSource.FromVisual(this).RootVisual 

Per ottenere la finestra principale:

Application.Current.MainWindow 
+2

Application.Current.MainWindow mi ha fornito esattamente ciò di cui avevo bisogno. Ho bisogno di accedere ai controlli nella finestra genitore da una finestra figlio aperta usando ShowDialog(). –

112

tenta di utilizzare

.Owner = Window.GetWindow(this) 
+3

Funziona alla grande, grazie. Ed è anche esattamente la risposta a questa domanda :-). –

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

attenti a questo. Ho avuto strani problemi durante l'esecuzione in 'VMWare Fusion' su un' Macintosh' - la finestra è apparso per un secondo e poi è svanita. – itsho

+0

Heads up: se hai un'altra finestra (finestra Splash, ecc.) Visualizzata - dovrai ** impostare il 'Proprietario' anche per essa! altrimenti otterrai alcuni comportamenti strani: la tua finestra principale non riceverà l'evento "OnActivated'/rimarrà sullo sfondo/sparirà improvvisamente, ecc. – itsho