.net 4.0 - Write a "partial" XAML TypeConverter that can convert to/from only a specific sub-type in a hierarchy -


given base class color @ least 2 sub-types, rgbcolor , cmykcolor:

abstract partial class color { }  sealed class rgbcolor : color {     public byte r { get; set; }     public byte g { get; set; }     public byte b { get; set; } }  sealed class cmykcolor : color {     public byte c { get; set; }     public byte m { get; set; }     public byte y { get; set; }     public byte k { get; set; } } 

and type going (de-) serialize to/from xaml .net 4's system.xaml.xamlservices:

class {     public color color { get; set; } } 

i able abbreviate rgb colors on xaml side this:

<something color="#010203" /> 

instead of having type out:

<something>   <something.color>     <rgbcolor r="1" g="2" b="3" />   </something.color> </something> 

this done typeconverter. (find current implementation @ end of question.) problem don't need, nor want, special abbreviation syntax other sub-types of color, such cmykcolor.

how can write typeconverter color works 1 of sub-types, rgbcolor?

(i have tried write typeconverter rgbcolor instead of color, xaml serializer doesn't appear use when encounters color property.)


// using system; // using system.componentmodel; // using system.globalization;  [typeconverter(typeof(colorconverter))] partial class color { }  sealed class colorconverter : typeconverter {     public override bool canconvertfrom(itypedescriptorcontext context, type sourcetype)     {         return sourcetype == typeof(string) || base.canconvertfrom(context, sourcetype);     }      public override bool canconvertto(itypedescriptorcontext context, type destinationtype)     {         return destinationtype == typeof(string) || base.canconvertto(context, destinationtype);     }      public override object convertfrom(itypedescriptorcontext context, cultureinfo culture, object value)     {         // omitted brevity's sake     }      public override object convertto(itypedescriptorcontext context, cultureinfo culture, object value, type destinationtype)     {         debug.assert(value color);         if (destinationtype == typeof(string))         {             if (value rgbcolor)             {                 var color = (rgbcolor)value;                 return string.format("#{0:x2}{1:x2}{2:x2}", color.r, color.g, color.b);             }             else             {                 throw new notsupportedexception(); // ?              }         }         else         {             return base.convertto(context, culture, value, destinationtype);         }     } } 

it turns out there different type of converter can used that: valueserializer. value serializers differ type converters in 2 key ways:

  • they can convert to/from strings. (other types aren't relevant xaml, anyway.)
  • they receive object converted in canconvert... stage. (that important bit.)

the main problem i've had value serializers having them invoked xamlservices.

here's solution:

first, must apply not value serializer, type converter base class:

// both types of converters must applied! [typeconverter(typeof(colorconverter))] [valueserializer(typeof(colorvalueserializer))] partial class color { } 

without type converter attribute, value serializer never invoked!

next, type converter must written converts strings (what msdn calls "the load path"):

sealed class colorconverter : typeconverter {     public override bool canconvertfrom(..., type sourcetype)     {         return sourcetype == typeof(string) || base.canconvertfrom(...);     }      public override bool canconvertto(..., type destinationtype)     {         return destinationtype != typeof(string) && base.canconvertto(...);         // above != not typo! must not let         // type converter conversion string.     }      public override object convertfrom(...)     {         // parse #rrggbb string , return corresponding rgbcolor     } } 

finally, let value serializer deal conversions string (the "save path"):

sealed class colorvalueserializer : valueserializer {     public override bool canconverttostring(object value, ...)     {         return value rgbcolor;     }      public override string converttostring(object value, ...)     {         // convert rgbcolor "#{r}{g}{b}" string     } } 

Comments

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -