【问题标题】:WPF: How do I set the Owner Window of a Dialog shown by a UserControl?WPF:如何设置用户控件显示的对话框的所有者窗口?
【发布时间】:2010-10-11 01:53:15
【问题描述】:

我有一个包含这三种类型的 WPF 应用程序...

  • 主窗口
  • UserControlZack
  • 窗口模式

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 对话框...

部分公共类 UserControlZack ... 私有子 SomeButton_Click(...) '实例化对话框并以模态方式打开... 暗箱 As WindowModal = New WindowModal() 框。所有者 = ????? box.ShowDialog() '如果对话框被接受,则处理用户输入的数据... 如果 (box.DialogResult.GetValueOrDefault = True) 那么 _SomeVar = box.SomeVar ... 万一 结束子 结束类

如何将 box.Owner 设置为正确的 Window,即我正在运行的 WindowMain 实例?

我不能使用box.Owner = Me.Owner,因为“'Owner' 不是 'ProjectName.UserControlZack' 的成员。”

我不能使用box.Owner = Me.Parent,因为它返回一个网格,而不是窗口。

我不能使用box.Owner = WindowMain,因为“'WindowMain' 是一种类型,不能用作表达式。”

【问题讨论】:

    标签: .net wpf vb.net dialog user-controls


    【解决方案1】:

    尝试使用

    .Owner = Window.GetWindow(this)
    

    【讨论】:

    • 效果很好,谢谢。也正是这个问题的答案:-)。
    • 另一个答案缺少 using 对模糊对象名称的引用。
    【解决方案2】:

    要获得您的控件所在的顶级窗口,假设有一个:

    (Window)PresentationSource.FromVisual(this).RootVisual
    

    获取主窗口:

    Application.Current.MainWindow
    

    【讨论】:

    • Application.Current.MainWindow 正是我所需要的。我需要从使用 ShowDialog() 打开的子窗口访问父窗口中的控件。
    【解决方案3】:
    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();
    

    【讨论】:

    • 小心这个。在Macintosh 上以VMWare Fusion 运行时,我遇到了奇怪的问题 - 窗口出现了一秒钟然后消失了。
    • 注意:如果您显示了另一个窗口(启动窗口等) - 您也将必须为其设置Owner!否则你会得到一些奇怪的行为——你的主窗口不会得到OnActivated事件/会留在后台/会突然消失,等等。
    【解决方案4】:

    更新以尝试帮助 cmets 的 Greg。该命令适用于主窗口菜单、用户控件中的按钮和用户控件中的上下文菜单。

    我会用命令来做。所以有一个类似于 Commands.cs 的类:

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

    在你的主窗口中注册这些:(你不需要canshow它默认为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。

    【讨论】:

    • 当我使用这种技术时,不会调用 CanExecute 事件来获取来自 UserControl 的引用。 CanExecute 似乎默认为 false,禁用命令所在的元素(在我的情况下是上下文菜单项)。父窗口中的 MenuItem 没有问题,并且已启用。
    • 跟命令路由有关。我的 UserControl 没有获得焦点,但有一个上下文菜单。如果在我尝试查看 UserControl 的上下文菜单时没有选择/聚焦任何元素,则不会路由命令事件。
    • 如果您想在问题中发布更多信息,我会看看能否帮助您。我在我正在制作的整个 WPF 应用程序中使用命令,我现在真的很喜欢它们。
    • 谢谢,安德鲁。我认为我已经想通了,但我不知道,直到我尝试它。我相信我只需要设置 CommandTarget="{Binding ElementName=This}" (这是 x:UserControl 的名称)。那应该从我的用户控件中获取命令事件,而不是从任何具有焦点的按钮中获取。 :)
    • 格雷格,我已经更新了,希望它可以帮助你。可能需要您提供更多信息才能更好地帮助您。
    【解决方案5】:

    我通过我的 XAML 一直爬回它来让它工作......

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

    但这似乎很不雅。有没有更好的办法?

    【讨论】:

    • 请参阅下文,了解如何使用 RoutedUICommand,我认为这是更优雅的方式。为 C# 道歉,我不是 VB 人!
    【解决方案6】:

    将窗口的名称更改为 WindowMain1 或其他名称,并将所有者设置为该名称怎么样?

    【讨论】:

    • "名称 'WindowMain1' 未声明。"
    • 啊,我明白了,没有仔细阅读问题,您是在用户控件类而不是主窗体类中执行此操作
    猜你喜欢
    • 1970-01-01
    • 2017-10-22
    • 1970-01-01
    • 2021-08-25
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    相关资源
    最近更新 更多