You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:01:30