WPF运行后XAML设计器报空引用错误且预览显示异常如何解决?
问题根源
这个问题是WPF XAML设计器的固有特性导致的,和运行时的XAML解析逻辑无关:
- 当你的自定义类同时继承了集合类型(这里是
List<string>)和IMultiValueConverter时,XAML设计器会优先将该类识别为集合类型,在资源实例化阶段会自动尝试初始化、扫描集合子项 - 你在XAML中声明该转换器资源时,仅设置了自定义的
Value属性,没有显式声明集合内容,设计器的内部解析顺序出现混乱,触发了未处理的NullReferenceException - 运行时不会出现该问题,是因为运行时的XAML解析器只会严格按照你编写的代码逻辑实例化对象,不会执行设计器特有的集合扫描、预填充逻辑
解决方案
以下方案都可以在保留你需要的「继承List<string>+暴露可设置属性」两个特性的前提下解决问题,可根据你的业务场景选择:
- 修改XAML资源声明,显式指定集合内容为空
在声明转换器资源时,显式添加空的字符串数组作为集合内容,告诉设计器该集合不需要额外填充:
首先在Window节点添加系统命名空间引用:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
然后修改资源声明:
<local:BuggyConverter x:Key="conv" Value="{x:Static Brushes.Yellow}"> <sys:String[] /> </local:BuggyConverter>
- 修改转换器类,重定向设计器的默认内容属性
给转换器类添加ContentProperty特性,将设计器默认要注入到集合的内容重定向到一个无关的占位属性上,不需要修改XAML代码:
[ContentProperty(nameof(DummyContent))] public class BuggyConverter : List<string>, IMultiValueConverter { // 占位属性,仅用于接收设计器的默认内容注入,不需要赋值和使用 public object DummyContent { get; set; } // 你原有业务逻辑的代码保持不变 public object Value { get; set; } public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) => Visibility.Visible; public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) => null; }
- 最优方案:用组合代替继承(如果业务允许)
如果你的业务逻辑不是必须要求转换器本身就是List<string>类型,推荐将继承改为组合,从根源上避免设计器将转换器识别为集合类型:
public class BuggyConverter : IMultiValueConverter { // 把原来的继承改为内置集合属性,业务上可以正常操作这个List public List<string> Items { get; set; } = new List<string>(); // 原有代码保持不变 public object Value { get; set; } public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) => Visibility.Visible; public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) => null; }
内容的提问来源于stack exchange,提问作者AyCe
相关产品推荐
相关产品推荐

