2009-03-03 3 views
51

У меня есть приложение WPF с этими тремя типами вещей ...WPF: Как установить окно владельца диалогового окна, отображаемого с помощью UserControl?

  • WindowMain
  • UserControlZack
  • WindowModal

UserControlZack1 сидит на моем 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 отображает окно окна 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 

Как установить box.Owner в правильное окно, мой исполняемый экземпляр WindowMain?

Я не могу использовать box.Owner = Me.Owner, потому что «« Владелец »не является членом« ProjectName.UserControlZack ».»

Я не могу использовать box.Owner = Me.Parent, потому что это возвращает Grid, а не Window.

Я не могу использовать box.Owner = WindowMain, потому что «WindowMain» является типом и не может использоваться как выражение ».

+1

Правильный, приемлемый ответ, вероятно, уже представлен. Основываясь исключительно на голосах, Мартину следует, вероятно, принять. – Emyr

ответ

0

Я получил его на работу, ползая весь путь обратно через мой XAML ...

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

Но это кажется довольно безвкусным. Есть ли способ лучше?

+0

См. Ниже, используя RoutedUICommand, который я считаю более элегантным. Извинения за C#, я не парень VB! –

0

Как насчет того, чтобы изменить имя окна на WindowMain1 или что-то еще, и присвоить этому владельцу?

+0

«Имя« WindowMain1 »не объявлено». –

+0

Ах, я вижу, недостаточно внимательно прочитал вопрос, вы делаете это внутри класса пользовательского контроля, а не из основного класса формы. – Davy8

5

Обновление, чтобы попытаться помочь Грегу из комментариев. Команда работает в главном меню окна, в элементе управления пользователя и в контекстном меню пользовательского элемента управления.

Я бы сделал это с помощью команд. Так что есть класс Commands.cs что-то вроде:

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

Регистрация это в главном окне: (вам не нужно canshow то по умолчанию оно истинно)

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

Это моя XAML для Главное окно:

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

Это XAML для моего пользовательского элемента управления (код по умолчанию позади только)

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

Вы можете принять это немного дальше и обработать команду в классе контроллера вместо этого и сделать это более бит MVC.

+0

Когда я использую эту технику, событие CanExecute не вызывается для ссылки из UserControl. Кажется, что CanExecute по умолчанию имеет значение false, отключив элемент, в котором находится команда (в моем случае это контекстное меню). Функция MenuItem в родительском окне не имеет проблем и включена. –

+0

Это как-то связано с командной маршрутизацией. Мой UserControl не получает фокус, но имеет контекстное меню. Если ни один элемент не выбран/сфокусирован, когда я пытаюсь просмотреть контекстное меню UserControl, событие команды не маршрутизируется. –

+0

Если вы хотите разместить дополнительную информацию в вопросе, я посмотрю, смогу ли я помочь вам. Я использую команды во всем приложении WPF, которое я создаю, и я действительно люблю их в данный момент. –

37

Чтобы получить окно верхнего уровня элемент управления находится в случае, если есть один:

(Window)PresentationSource.FromVisual(this).RootVisual 

Чтобы получить основное окно:

Application.Current.MainWindow 
+2

Application.Current.MainWindow дал мне именно то, что мне было нужно. Мне нужно получить доступ к элементам управления в родительском окне из дочернего окна, открытого с помощью ShowDialog(). –

112

Попробуйте использовать

.Owner = Window.GetWindow(this) 
+3

Отлично работает, спасибо. И это также ответ на этот вопрос :-). –

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

Остерегайтесь этого. У меня возникли странные проблемы при запуске в «VMWare Fusion» в окне «Macintosh», которое появилось в течение секунды, а затем исчезло. – itsho

+0

Heads up: если у вас появилось другое окно (окно Splash и т. Д.) - вы ** должны ** установить для него «Владелец»! в противном случае вы получите какое-то странное поведение - ваше главное окно не получит событие OnActivated/останется в фоновом режиме/внезапно исчезнет и т. д. – itsho