WinUI3中DoubleCollection类型Dependency Property致应用崩溃
WinUI 3自定义控件绑定LineStrokeDashArray崩溃解决办法
问题情况
我在WinUI 3里做了个叫testControl的自定义控件,定义了LineStrokeDashArray这个依赖属性,代码是这样的:
public class testControl : Control { public DoubleCollection LineStrokeDashArray { get { return (DoubleCollection)GetValue(LineStrokeDashArrayProperty); } set { SetValue(LineStrokeDashArrayProperty, value); } } public static readonly DependencyProperty LineStrokeDashArrayProperty = DependencyProperty.Register("LineStrokeDashArray", typeof(DoubleCollection), typeof(testControl), new PropertyMetadata(default(DoubleCollection))); }
然后在控件的ControlTemplate里绑定了这个属性:
<Line VerticalAlignment="Center" Stretch="Fill" Stroke="{TemplateBinding LineStroke}" StrokeDashArray="{TemplateBinding LineStrokeDashArray}" StrokeEndLineCap="Square" StrokeStartLineCap="Square" StrokeThickness="{TemplateBinding LineStrokeThickness}" X2="1" />
结果用<local:testControl LineStrokeDashArray="2,2" />调用控件时,直接崩了。我试过把属性元数据改成new PropertyMetadata(new DoubleCollection()),还是崩,而且WinUI 3没给详细报错信息,只显示崩溃界面。
问题原因
WinUI 3的XAML解析器没办法自动把字符串"2,2"转换成DoubleCollection类型,直接赋值会触发类型转换异常或者空引用,导致应用崩溃。另外如果在PropertyMetadata里直接初始化new DoubleCollection(),所有控件实例会共享同一个集合,也可能引发未知问题。
修复方案
1. 给属性加类型转换器
让XAML能正确解析字符串到DoubleCollection,修改依赖属性定义和属性标记:
[TypeConverter(typeof(DoubleCollectionConverter))] public DoubleCollection LineStrokeDashArray { get { return (DoubleCollection)GetValue(LineStrokeDashArrayProperty); } set { SetValue(LineStrokeDashArrayProperty, value); } } public static readonly DependencyProperty LineStrokeDashArrayProperty = DependencyProperty.Register( nameof(LineStrokeDashArray), typeof(DoubleCollection), typeof(testControl), new PropertyMetadata(null, null, CoerceLineStrokeDashArray)); // 强制值回调,确保空值时返回空集合而非null private static object CoerceLineStrokeDashArray(DependencyObject d, object baseValue) { return baseValue ?? new DoubleCollection(); }
2. 替换TemplateBinding为RelativeSource绑定(可选)
如果TemplateBinding还是有问题,换成TemplatedParent绑定更稳妥:
<Line VerticalAlignment="Center" Stretch="Fill" Stroke="{Binding LineStroke, RelativeSource={RelativeSource TemplatedParent}}" StrokeDashArray="{Binding LineStrokeDashArray, RelativeSource={RelativeSource TemplatedParent}}" StrokeEndLineCap="Square" StrokeStartLineCap="Square" StrokeThickness="{Binding LineStrokeThickness, RelativeSource={RelativeSource TemplatedParent}}" X2="1" />
3. 正确初始化默认值
别在PropertyMetadata里直接创建集合实例,改在构造函数里初始化:
public testControl() { DefaultStyleKey = typeof(testControl); LineStrokeDashArray = LineStrokeDashArray ?? new DoubleCollection(); }
验证
改完之后用<local:testControl LineStrokeDashArray="2,2" />调用,应用不再崩溃,Line控件能正常显示虚线样式。
内容的提问来源于stack exchange,提问作者Power Code
相关产品推荐
相关产品推荐

