在VS2022的 XAML IntelliSense中,对于自定义的WPF依赖属性,TypeConverter.GetStandardValues未被调用
TypeConverter.GetStandardValues未被VS2022的 XAML IntelliSense调用,用于自定义WPF依赖属性
我有一个包含两个项目的WPF解决方案:
- MyLibrary — WPF类库,包含自定义控件和TypeConverter
- MyApp — 参考MyLibrary的 WPF应用,在其中编写XAML
我希望在XAML编辑器(MyApp中)按Ctrl+Space时,能弹出一个自定义DependencyProperty的候选值下拉列表。我实现了一个 TypeConverter,配合 GetStandardValues,但并未出现任何完成列表。
MyLibrary代码
[TypeConverter(typeof(FieldNameConverter))]
public class FieldName
{
public string Value { get; set; } = string.Empty;
public FieldName() { }
public FieldName(string value) => Value = value;
public override string ToString() => Value;
}
public class FieldNameConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
=> sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
=> value is string s ? new FieldName(s) : base.ConvertFrom(context, culture, value);
public override bool GetStandardValuesSupported(ITypeDescriptorContext context) => true;
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) => false;
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
=> new StandardValuesCollection(new[] { "AAA", "BBB", "CCC" });
}
public class PropertyAxisBar : Control
{
public static readonly DependencyProperty FieldNameProperty =
DependencyProperty.Register(
nameof(FieldName),
typeof(FieldName),
typeof(PropertyAxisBar),
new PropertyMetadata(new FieldName()));
// Variant 1: TypeConverter on the property
[TypeConverter(typeof(FieldNameConverter))]
public FieldName FieldName
{
get => (FieldName)GetValue(FieldNameProperty);
set => SetValue(FieldNameProperty, value);
}
}
我还测试了 Variant 2 — [TypeConverter] 应用于类本身(如上所示),但属性上没有该属性标记。两种变体都不起作用。
MyApp XAML
<local:PropertyAxisBar FieldName="|" />
<!-- Ctrl+Space here — nothing appears -->
我已验证的内容
Brush属性在同一控件上确实会显示完成列表(SystemBrushes)——因此IntelliSense总体上是可用的- 在XAML编辑器中按Ctrl+Space时,
GetStandardValues的断点从未命中 [TypeConverter]属性位于FieldName类上- VS2022、.NET 6 / .NET 4.8、WPF
问题
VS2022的 XAML编辑器是否会对自定义类型调用 TypeConverter.GetStandardValues?
如果不会——在XAML编辑器中为DependencyProperty值提供自定义完成列表的正确方式是什么?
是否只有使用单独的 .Design 程序集并包含 IProvideAttributeTable 的方案才是可选项?
解决方案
对普通XAML属性值的建议仅在XAML编辑器能够静态理解的情况下才可用:基本字面值、布尔值、枚举、已知的WPF/XAML值类型、资源、绑定、元素名称、标记扩展等。其中有些在设计时实际上是内置支持,而不是通过分析器动态发现。
IntelliSense通常不会实例化任意自定义 TypeConverter 并调用 GetStandardValues() 来发现可能的值。TypeConverter 主要在XAML处理器将普通字符串属性值解析为目标CLR类型时使用。它并非用于设计时。
一个实际可行的选项是在有效集合有限时将属性类型设为枚举。枚举值便于IntelliSense进行检查,因此编辑器可以针对简单属性语法提示定义的枚举成员。
对于非枚举的自定义值对象,IntelliSense通常无法知道哪些字符串是有效的,因为这类知识存放在自定义转换器逻辑中。解析属性类型的唯一路径是通过 TypeConverter。但转换器是在构建时被调用的(有时也会在设计器渲染UI时在设计器预览窗格中被调用)。
使用 {x:Static ...} 也可以获得更好的完成,因为此时值以类型/成员引用的形式表达,而不是神秘字符串。标记扩展路径绕过目标属性的常规字符串到类型的转换:扩展直接提供值。
因此,结论是如果你关心IntelliSense的支持且该类型允许,应该尝试将属性类型设为枚举。