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

问题描述 投票:0回答:13

我自己设计的 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)

但我认为这些消息并不是很有帮助...

如何修复或抑制此异常?

c# wpf exception user-controls
13个回答
30
投票

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

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

有关详细信息和屏幕截图,请参阅此处


7
投票

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


4
投票

我倾向于在

LicenseManager
中使用
System.ComponentModel
类来避免我的 ViewModels 在设计时抛出讨厌的错误。例如:

public MyViewModel()
{
  if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
  {
    // Do runtime stuff
  }
}

2
投票

调整@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...
}

也对我有用,我只是不想用额外的返回语句来缩短我的方法。我会赞成他的回答,还没有代表。


2
投票

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

public MainWindow()
{
    InitializeComponent();
    if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
        return;

    //code
}

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


1
投票

你可以这样做:

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

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


1
投票

我有类似的问题。您只需要转到工具>选项> XAML设计器并启用选项

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

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


0
投票

VS 2017 UWP:

if (false == Windows.ApplicationModel.DesignMode.DesignModeEnabled)
{
     // Anything in here need not be OK at Design time in Visual Studio                 
}

0
投票

在 XAML 的“部分类”中,如果可以看到“

[XamlCompilation(XamlCompilationOptions.Compile)]
”, 只需删除该行,然后再次尝试构建。


0
投票

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


0
投票

在错误列表窗口中将“Build only”选项更改为“Intellisense only”


0
投票

在重构期间,某些类的 C# 名称空间发生了变化。

xmlns
名称也相应更改。

但是在一个地方

xmlns
被改变了它不应该是的地方。例如,这样的代码:

<OldNS:SomeControl ... />

被错误地改为

<NewNS:SomeControl ... />

控件

SomeControl
因此不存在于
NewNS
映射指示的命名空间中。

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

最终找到并修复这个错误,问题就解决了。


0
投票

对于 XAML 中的某些组件(如 TabControl),VS2022 17.5.4 是否存在此问题(此问题仅在最近的 vs 更新后发生)

从谷歌找到这个解决方案:

然后注意到@windowsill评论也提到了这个 如何在设计时避免 XAML 代码中的“对象引用未设置到对象的实例”异常?

© www.soinside.com 2019 - 2024. All rights reserved.