I have a custom UITypeEditor that is in use for Colour Selection with my program using the propertygrid, but I can't seem to get it to activate if I just expose system.drawing.color. I need to wrap the Color with a CustomType before it will invoke my UITypeEditor.
Note the Property TheColour it works. The Colour doesn't.
When I open the propertyGrid, I can see GetEditStyle
is called via both methods, but when it comes to EditValue
it is only called when you select TheColour in the propertygrid. The Normal Colour dropdown is shown when you select Colour Property
What am I missing?
<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
The problem is that it is noticing that the associated TypeConverter
supports enumerated values. We need to disable that; note we can also inherit from the default implementations to get things like the color preview painting (examples in C#, but should be easy to translate):
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;}
}
If you want this to apply to all Color
properties, there is also a way to do it such that you don't need to decorate every property; somewhere during your app's initialization code, execute:
TypeDescriptor.AddAttributes(typeof(Color),
new EditorAttribute(typeof(MyColorEditor), typeof(UITypeEditor)),
new TypeConverterAttribute(typeof(MyColorConverter)));
I think i've found a solution to this problem.
I needed to implement a TypeConverter to force the GetStandardValuesSupported to return false.
I can then do away with TheColour property and just use.
<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
it's a bit ugly because the colour is represented in the box as the colour selected, but the text is printed in the rest of the PropertyGridCell so I also added some overrides to the Converter to just return empty strings. (I would have preferred to paint the entire cell the colour rather than just the little box).
The Converter class.
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
精彩评论