C# WPF无法获取父窗口

11

我有一个在窗口中托管的WPF页面。但是当我试图使用它时,我会得到空异常。这段代码可以在另一个方法中使用,但不是所有的方法,为什么会这样呢?请给予建议。

 NewPage page = new NewPage ();
 Window w = Window.GetWindow(this.Parent);
 w.Content = page;

编辑:

这里是完整的代码:

    public HandOverListPage() {
        InitializeComponent();

        _settings = new Settings();
    }


    public void ShowCurrentInUseAssignment() {

        _currentDoc = (App.Current as App).SelectedHandOverDoc;

        var r = from item in (App.Current as App).SelectedHandOverDoc.Items
                where item.Status != 20
                select item;

        if(r.Count() == 0) {
            //Report assignment to QP with status finished
            ReportAssignment();

            HandOverPage page = new HandOverPage();

            Window w = Window.GetWindow(this.Parent);
            w.Content = page;

            return;
        } else {
            ICollectionView view = CollectionViewSource.GetDefaultView((App.Current as App).SelectedHandOverDoc.Items);
            view.SortDescriptions.Add(new SortDescription("Status", ListSortDirection.Ascending));

            ListBoxAssignmentItems.ItemsSource = view;
        }

        TxtBlockCounter.Text = r.Count().ToString();
    }

这个错误信息:

{"值不能为 null。\r\n参数名: dependencyObject"}

我在使用立即窗口时遇到了这个错误。

    ?this.GetType()
{Name = "HandOverListPage" FullName = "QP_Truck.Pages.HandOverListPage"}
    [System.RuntimeType]: {Name = "HandOverListPage" FullName = "QP_Truck.Pages.HandOverListPage"}
    base {System.Reflection.MemberInfo}: {Name = "HandOverListPage" FullName = "QP_Truck.Pages.HandOverListPage"}
    Assembly: {QP Truck, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
    AssemblyQualifiedName: "QP_Truck.Pages.HandOverListPage, QP Truck, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
    Attributes: Public | BeforeFieldInit
    BaseType: {Name = "Page" FullName = "System.Windows.Controls.Page"}
    ContainsGenericParameters: false
    DeclaringMethod: 'this.GetType().DeclaringMethod' threw an exception of type 'System.InvalidOperationException'
    DeclaringType: null
    FullName: "QP_Truck.Pages.HandOverListPage"
    GenericParameterAttributes: 'this.GetType().GenericParameterAttributes' threw an exception of type 'System.InvalidOperationException'
    GenericParameterPosition: 'this.GetType().GenericParameterPosition' threw an exception of type 'System.InvalidOperationException'
    GUID: {93eb30b9-a64e-3c6b-9182-0f93582d188d}
    HasElementType: false
    IsAbstract: false
    IsAnsiClass: true
    IsArray: false
    IsAutoClass: false
    IsAutoLayout: true
    IsByRef: false
    IsClass: true
    IsCOMObject: false
    IsContextful: false
    IsEnum: false
    IsExplicitLayout: false
    IsGenericParameter: false
    IsGenericType: false
    IsGenericTypeDefinition: false
    IsImport: false
    IsInterface: false
    IsLayoutSequential: false
    IsMarshalByRef: false
    IsNested: false
    IsNestedAssembly: false
    IsNestedFamANDAssem: false
    IsNestedFamily: false
    IsNestedFamORAssem: false
    IsNestedPrivate: false
    IsNestedPublic: false
    IsNotPublic: false
    IsPointer: false
    IsPrimitive: false
    IsPublic: true
    IsSealed: false
    IsSerializable: false
    IsSpecialName: false
    IsUnicodeClass: false
    IsValueType: false
    IsVisible: true
    MemberType: TypeInfo
    Module: {QP Truck.exe}
    Namespace: "QP_Truck.Pages"
    ReflectedType: null
    StructLayoutAttribute: {System.Runtime.InteropServices.StructLayoutAttribute}
    TypeHandle: {System.RuntimeTypeHandle}
    TypeInitializer: null
    UnderlyingSystemType: {Name = "HandOverListPage" FullName = "QP_Truck.Pages.HandOverListPage"}
6个回答

18

你发布的代码是在构造函数中吗?

UserControl 的父对象在其构造函数中始终为空,因此 this.Parent 返回 null 引用。因此,调用 Window.GetWindow(this.Parent) 会引发 ArgumentNullException,因为您指定的依赖对象尚未创建。

要解决此问题,您需要将代码放置在 Initialized 事件处理程序中。当引发此事件时,您可以确保 UserControl 已被创建。


我现在已经在我的帖子中添加了立即窗口的输出。 - Tan
这对我有效。而且可能应该被接受为答案。 - gunwin
这正是我怀疑为什么我永远无法获取父窗口的原因。+1 - Jacky Cheng
2
在我的情况下,我不得不在 Loaded 中调用它而不是 Initialized。WPF 可能会多次运行 Loaded。 - Vimes

7
尝试使用“Owner”属性,您需要分配它。
示例:
public Activity ShowLookUp(Window owner)
{
     ActivityLookUp lookup = new ActivityLookUp();
     lookup.Owner = owner;
     lookup.ShowDialog();
}

3
我不确定我理解这个。为什么这比Window.GetWindow更好?你能提供更多的解释吗? - Cody Gray
我并不是说这是更好的解决方案,这只是我解决问题的方式。 - klm_
我同意 - 页面不会自动拥有所有者,您需要显式设置其所有者。 - Amittai Shapira

0
你可以使用不同的选项:
从Child UserControl的Code Behind中
- VisualTreeHelper.GetParent(this) - LogicalTreeHelper.GetParent(this) - this.Parent - Window.GetWindow(this); → 如果你想要容器窗口
但是如果在构造函数中调用它们,所有这些选项都会返回null,因为子控件的初始化发生在将控件附加到视觉树之前。
所以你必须在子User Control完成加载后调用它们。
public MyChildUserControl()
{
    InitializeComponent();
    
    //Postponing the retrieval of the parent using the OnLoaded event
    Loaded += (s, e) =>
    {
        var p = VisualTreeHelper.GetParent(this);

        while (!(ucParent is UserControl))
        {
            ucParent = LogicalTreeHelper.GetParent((DependencyObject) this);
        }



        _parentWindow = Window.GetWindow(this);
        /// whatever you are going to do with parent window
    };
}

就像这位https://stackoverflow.com/a/39477256/196210所说:


0

虽然有可接受的答案列出,但它们似乎都过于复杂化了这个问题。

页面没有父级,但是由于页面只是一个页面而不是窗口,对自身调用“获取窗口”将返回窗口引用而不是页面,因此你所需要的只是:

Window w = Window.GetWindow(this);

只需要省略 .Parent 即可。


0
当您调用this.Parent时,您处于什么上下文中?您是否期望this是对page对象的引用?从您添加的代码示例来看,情况并非如此。我建议您在Window.GetWindow行处设置断点,并在立即窗口中执行?this.GetType()以查看发生了什么。

0

标签有时很有用。

为什么不试试这个。

// "this" is your Window
YourFrame.Content = new YourPage() { Tag = this };

在你的页面中,尝试这个

Window w = (Window)this.Tag;
// and do all the Window wonders

:)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接