WPF: Как настроить окно владельца диалогового окна, отображаемого в UserControl? - PullRequest
54 голосов
/ 03 марта 2009

У меня есть приложение WPF с этими тремя типами вещей ...

  • 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 на правильное Window, мой запущенный экземпляр WindowMain?

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

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

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

Ответы [ 6 ]

123 голосов
/ 04 марта 2009

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

.Owner = Window.GetWindow(this)
40 голосов
/ 04 марта 2009

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

(Window)PresentationSource.FromVisual(this).RootVisual

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

Application.Current.MainWindow
8 голосов
/ 03 октября 2011
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();
5 голосов
/ 03 марта 2009

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

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

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

Зарегистрируйте их в главном окне: (вам не нужно, чтобы по умолчанию показывалось значение 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;
    }

Это мой 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 голосов
/ 03 марта 2009

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

0 голосов
/ 03 марта 2009

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

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

Но это выглядит довольно не элегантно. Есть ли лучший способ?

...