如何在设计时避免 XAML 代码中的“对象引用未设置为对象的实例”异常?

Posted

技术标签:

【中文标题】如何在设计时避免 XAML 代码中的“对象引用未设置为对象的实例”异常?【英文标题】:How to avoid a "object reference not set to an instance of an object" exception in XAML code at design time? 【发布时间】:2013-07-16 02:38:07 【问题描述】:

我自己设计的 wpf 用户控件有问题。 问题是当我在我的程序中实现用户控件时,我在设计时在 XAML 代码中得到了 object reference not set to an instance of an object 异常。

设计师向我展示了以下信息:

at
Microsoft.Expression.Platform.InstanceBuilders.InstanceBuilderOperations.InstantiateType(Type
type, Boolean supportInternal)    at
Microsoft.Expression.Platform.InstanceBuilders.ClrObjectInstanceBuilder.InstantiateTargetType(IInstanceBuilderContext
context, ViewNode viewNode)    at
Microsoft.Expression.Platform.InstanceBuilders.ClrObjectInstanceBuilder.Instantiate(IInstanceBuilderContext
context, ViewNode viewNode)    at
Microsoft.Expression.WpfPlatform.InstanceBuilders.FrameworkElementInstanceBuilder.Instantiate(IInstanceBuilderContext
context, ViewNode viewNode)    at
Microsoft.Expression.WpfPlatform.InstanceBuilders.UserControlInstanceBuilder.Instantiate(IInstanceBuilderContext
context, ViewNode viewNode)    at
Microsoft.Expression.Platform.InstanceBuilders.ViewNodeManager.CreateInstance(IInstanceBuilder
builder, ViewNode viewNode)

但我认为这些消息并没有真正的帮助......

如何修复或抑制此异常?

【问题讨论】:

设计师应该向您展示错误的堆栈跟踪 - 错误实际发生在哪里? 请贴出引发错误的代码部分。提供的信息很难回答这个问题 WPF, 'Object reference not set to an instance of an object' in Designer 的可能重复项 是的,我知道另一个问题,但没有任何描述的解决方案可以解决我的问题。在问这个问题之前,我阅读了另一个问题。 【参考方案1】:

如果您在 XAML 中设置了“未将对象引用设置为对象的实例”,但您的应用程序编译并运行良好,您通常会发现其原因是构造函数中无法在设计时解决的问题时间。

您只需单击位于设计器视图底部的“禁用项目代码”按钮,Visual Studio 设计器将停止尝试构造实例以提供设计时数据视图。

有关详细信息和屏幕截图,请参阅here。

【讨论】:

如果当前xaml上的设计器没有加载,“禁用项目代码”按钮将不可用。加载一个好的 xaml 以使按钮可用。该设置现在将应用于拒绝加载的 xaml。 如果您没有看到按钮,请尝试评论 propblamitc 行,然后您会得到它 我的构造函数中有一些代码导致了这种现象的发生 - 它困扰着我(可以这么说)很高兴你在这里帮助了我。 在我的 VS 中,该按钮让我可以选择“显示所有控件”或“仅显示平台控件”。选择后者会导致 xaml 在设计器中呈现并删除未设置为对象错误实例的对象引用。【参考方案2】:

在您的构造函数中发生的任何事情都会在设计时引发异常。我遇到了同样的问题 - 我只是在有问题的代码周围尝试了一下 - 在我的情况下,我正在调用 ServiceLocator.Current,因为我正在使用 IoC 容器。但是在设计时没有容器。所以我包裹了一个try catch来抑制错误并且它起作用了。不是最好的解决方案......但它是一个解决方案。

【讨论】:

这个答案是 0 意义。问题出在 XAML 中,没有办法“只是尝试捕获”。如果一个人知道“有问题的代码”是什么,就不会有问题。 @N_tro_P xaml 后面有一个 .cs 文件,它有一个构造函数。 你认为在 InitializeComponent() 周围包裹一个 try catch 会捕获有问题的代码吗?另外...某些 XAML 没有构造函数,例如资源字典。这尤其是我的情况以及我是如何来到这里的。 我不认为 .Net 设计时错误在乎你的信念。同样,后面甚至没有必要的代码。也许在海报案例中,正如他在细节中所说的“用户控制”,但问题是如何处理 XAML 中的设计时错误,这也可能是 RD。在这种情况下没有构造函数。 也许它不适用于您的情况。我认为,如果您分享您的具体情况以及如何解决它,那将比花言巧语更有成效。【参考方案3】:

我倾向于在System.ComponentModel 中使用LicenseManager 类来避免我的ViewModel 在设计时抛出令人讨厌的错误。例如:

public MyViewModel()

  if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
  
    // Do runtime stuff
  

【讨论】:

【参考方案4】:

调整@BobHorn 的例子,我得到了这个为我工作:

public class ViewModel

    public ViewModel()
    
        if (!IsInDesignMode)
        
            //Constructor code here...
        
    
    public bool IsInDesignMode
    
        get
        
            var prop = DesignerProperties.IsInDesignModeProperty;
            return (bool)DependencyPropertyDescriptor
                .FromProperty(prop, typeof(FrameworkElement))
                .Metadata.DefaultValue;
        
    

虽然使用他对构造函数的确切建议

public Main()

    if (IsInDesignMode)  return; 
    //Constructor code here...

也对我有用,我只是不想用额外的 return 语句来短路我的方法。我会投票赞成他的答案,但还没有代表。

【讨论】:

【参考方案5】:

你可以这样做:

using System.ComponentModel;
using System.Windows;

/// <summary>
/// WPF Design Mode helper class.
/// </summary>
public static class DesignMode

    private static bool? _isInDesignMode;

    /// <summary>
    /// Gets a value indicating whether the control is in design mode (running in Blend
    /// or Visual Studio).
    /// </summary>
    public static bool IsInDesignMode
    
        get
        
            if (!_isInDesignMode.HasValue)
            
                var prop = DesignerProperties.IsInDesignModeProperty;
                _isInDesignMode
                    = (bool)DependencyPropertyDescriptor
                    .FromProperty(prop, typeof(FrameworkElement))
                    .Metadata.DefaultValue;
            

            return _isInDesignMode.Value;
        
    

然后,作为视图(或视图模型)构造函数的第一行,您可以执行以下操作:

if (DesignMode.IsInDesignMode)  return; 

这样您的代码只会在您实际运行时运行。

【讨论】:

【参考方案6】:

我遇到了类似的问题。您只需要转到 Tools> Options> XAML Designer 并启用该选项

“在 XAML 设计器中运行项目代码”。

最后重新启动 Visual Studio。我希望这会有所帮助。

【讨论】:

您使用的是哪个版本的 Visual Studio?我在 Visual Studio 2013 中找不到“XAML 设计器”部分。 抱歉来晚了。无论如何,我使用的是 VS 2015。 啊啊,来晚了,对 :) 我确实在最近的 VS 版本中发现了这个选项。 所以每两年一个答案? :b 我正在使用 VS 2019,在 XAML 设计器菜单中找不到该选项..【参考方案7】:

当您在设计器中处理 WIndow/UserControl 时,它会“运行”无参数构造函数。 如果你的代码依赖于其他一些代码通常提供的东西,那么这通常会导致问题。 设计器不会首先运行任何其他代码,因此通常在其他地方提供的依赖项可能会丢失并导致错误。 抑制这些是检测该代码是否在设计器中运行的问题。 只返回构造函数通常是最方便的:

public MainWindow()

    InitializeComponent();
    if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
        return;

    //code

更多详情https://social.technet.microsoft.com/wiki/contents/articles/29874.aspx?Redirected=true

【讨论】:

【参考方案8】:

VS 2017 UWP:

if (false == Windows.ApplicationModel.DesignMode.DesignModeEnabled)

     // Anything in here need not be OK at Design time in Visual Studio                 

【讨论】:

【参考方案9】:

在你 XAML 的“部分类”中,如果你能看到“[XamlCompilation(XamlCompilationOptions.Compile)]”, 只需删除该行,然后再次尝试构建。

【讨论】:

【参考方案10】:

如果其他人来到这里,我无意中将我的 MainWindow.xaml 文件拖到了一个子文件夹中。将其拖回即可解决问题。

【讨论】:

【参考方案11】:

在错误列表窗口中将“仅构建”选项更改为“仅智能感知”

【讨论】:

【参考方案12】:

在重构期间,某些类的 C# 命名空间发生了变化。 xmlns 名称也相应更改。

然而,xmlns 在一个地方被更改了它不应该在的地方。例如,这样的代码:

<OldNS:SomeControl ... />

被错误地更改为

<NewNS:SomeControl ... />

因此,NewNS 映射指示的命名空间中不存在控件 SomeControl

我没有将其标记为特定错误,而是出于某种原因得到了“对象引用未设置为对象的实例”异常,而不知道来源。

最终发现并修复了这个错误解决了问题。

【讨论】:

以上是关于如何在设计时避免 XAML 代码中的“对象引用未设置为对象的实例”异常?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UWP 类库中使用 XAML 静态资源和设计时数据

如何在 C++ 运行时组件中的 Windows Phone 8.1 XAML 应用程序中使用 C++ dll

删除在运行时创建的资源的 XAML 设计器错误?

如何在不创建 ViewModel 对象的情况下指定 DataContext (ViewModel) 类型以在 XAML 编辑器中进行设计时绑定检查? [复制]

如何在 Visual Studio 2008 中禁用 XAML 文件的“代码分析”?

[UWP]XAML中的响应式布局技术