如何强制使用自定义UITypeEditor来处理系统类型

4
我有一个自定义的UITypeEditor,用于我的程序中使用属性网格进行颜色选择,但是如果我仅公开system.drawing.color,似乎无法激活它。在调用我的UITypeEditor之前,我需要使用CustomType包装Color。
请注意属性“TheColour”可以正常工作,“Colour”不能。
当我打开属性网格时,我可以看到通过两种方法调用GetEditStyle,但是在选择颜色属性时,只有选择TheColour时才会调用EditValue。普通颜色下拉菜单显示在选择颜色属性时。
我错过了什么?
<CategoryAttribute("Order Colour"), _
 Browsable(True), _
 DisplayName("The Colour"), _
 Description("The background colour for orders from this terminal"), _
EditorAttribute(GetType(IKMDependency.ColourSelectorEditor), _ 
GetType(System.Drawing.Design.UITypeEditor))> _
Public Property TheColour() As MyColour
    Get
        Return mMyColor
    End Get
    Set(ByVal value As MyColour)
        If value.Colour <> mMyColor.Colour Then
            mColor = value.Colour
            mMyColor = value
            mIsDirty = True
        End If
    End Set
End Property

<CategoryAttribute("Order Colour"), _
 Browsable(True), _
 DisplayName("Colour"), _
 Description("The background colour for orders from this terminal"), _
EditorAttribute(GetType(IKMDependency.ColourSelectorEditor), _ 
GetType(System.Drawing.Design.UITypeEditor))> _
Public Property Colour() As Color
    Get
        Return mColor
    End Get
    Set(ByVal value As Color)
        If mColor <> value Then
            mColor = value
            mMyColor = New MyColour(mColor)
            mIsDirty = True
        End If
    End Set
End Property

找到了 - 请看我回答的编辑。 - Marc Gravell
2个回答

6
问题在于它注意到相关的 TypeConverter 支持枚举值。我们需要禁用它;请注意,我们还可以从默认实现中继承,以获得像颜色预览绘画这样的功能(示例使用C#,但应易于翻译):
class MyColorEditor : ColorEditor {
    public override UITypeEditorEditStyle GetEditStyle(
        ITypeDescriptorContext context) {
         return UITypeEditorEditStyle.Modal;
    }
    public override object  EditValue(
       ITypeDescriptorContext context, IServiceProvider provider, object value) {
        MessageBox.Show(
              "We could show an editor here, but you meant Green, right?");
       return Color.Green;
    }
}
class MyColorConverter : ColorConverter { // reference: System.Drawing.Design.dll
    public override bool GetStandardValuesSupported(
            ITypeDescriptorContext context) {
        return false;
    }
}
class TestObject
{
    [Category("Order Colour"), Browsable(true), DisplayName("Colour")]
    [Description("The background colour for orders from this terminal")]
    [Editor(typeof(MyColorEditor), typeof(UITypeEditor))]
    [TypeConverter(typeof(MyColorConverter))]
    public Color Colour {get;set;}
}

如果您希望将此应用于所有Color属性,也有一种方法可以做到这一点,而不需要装饰每个属性;在应用程序的初始化代码的某个地方执行:

TypeDescriptor.AddAttributes(typeof(Color),
    new EditorAttribute(typeof(MyColorEditor), typeof(UITypeEditor)),
    new TypeConverterAttribute(typeof(MyColorConverter)));

哈哈,我在你发布更新之前就已经找到了解决方案,只是当我发布补充说明时才看到它更新了一次。可惜的是,没有办法让网格绘制整个单元格而不仅仅是小预览框。 - Paul Farry
感谢您提供使用TypeDescriptor.AddAttributes的提示,这对我来说是新的。 - wangzq
你能告诉我你是如何发现有一个关联的TypeConverter的吗?我正在尝试为Dictionary<string,string>做这个,想知道如何浏览已加载的转换器以及在类型中注册了哪些编辑器,例如在linqpad中。 - Maslow
@Maslow 你可以从查找类型的EditorAttribute和TypeConverterAttribute开始,但由于列表可能在运行时更改,因此这并不是详尽无遗的。 - Marc Gravell
我想象这并不是详尽无遗的,但它向我展示了我想知道的内容 TypeDescriptor.GetConverter(new Dictionary<string,string>()).Dump(); - Maslow
也许你可以看一下这个链接?http://stackoverflow.com/questions/6141010/how-do-you-hook-an-editor-for-tfs-2010-wf-buildprocesstemplate-arguments-for-buil - Maslow

0

我认为我已经找到了解决这个问题的方法。

我需要实现一个TypeConverter来强制GetStandardValuesSupported返回false。

然后我就可以放弃TheColour属性,只需使用。

<CategoryAttribute("Order Colour"), _
Browsable(True), _
DisplayName("Custom Colour to Use"), _
Description("The background colour for orders from this terminal"), _
EditorAttribute(GetType(IKMDependency.ColourSelectorEditor), GetType(System.Drawing.Design.UITypeEditor)), _
TypeConverter(GetType(ColourTypeConverter))> _
Public Property Colour() As Color
    Get
        Return mColor
    End Get
    Set(ByVal value As Color)
        If mColor <> value Then
            mColor = value
            mIsDirty = True
        End If
    End Set
End Property

这有点丑,因为颜色在框中表示为所选的颜色,但文本印在其余的PropertyGridCell中,所以我还添加了一些覆盖到转换器中,只返回空字符串。(我更喜欢将整个单元格涂成颜色而不仅仅是小框)。

转换器类。

Public Class ColourTypeConverter
    Inherits TypeConverter

    Public Overrides Function GetStandardValuesSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
        Return False
    End Function

    Public Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
        If sourceType Is GetType(String) Then Return False
        Return MyBase.CanConvertFrom(context, sourceType)
    End Function

    Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
        If destinationType Is GetType(String) Then Return String.Empty
        Return MyBase.ConvertTo(context, culture, value, destinationType)
    End Function

    Public Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
        Return MyBase.ConvertFrom(context, culture, value)
    End Function

    Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
        If destinationType Is GetType(String) Then Return False
        Return MyBase.CanConvertTo(context, destinationType)
    End Function
End Class

如果你从ColorConverter继承而不是TypeConverter,你将获得一个更完整的实现。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接