wpf - Why Are ICommand Properties Treated Specially by Bindings? -


so far, had impression wpf looks @ actual type of object gets via binding or in other way determine templates, styles , representation use. however, confronted situation makes seem wpf (also?) looks @ declared property type reason.

this exemplary view model:

using system; using system.windows.input;  public class simpleviewmodel {     private class myexamplecommand : icommand     {         public bool canexecute(object parameter)         {             return true;         }          public event eventhandler canexecutechanged;          public void execute(object parameter)         {         }          public override string tostring()         {             return "test";         }     }      private icommand examplecommand;      public icommand examplecommand     {                 {             if (examplecommand == null)             {                 examplecommand = new myexamplecommand();             }             return examplecommand;         }     } } 

use instance of class data context in window , add button:

<button>     <textblock text="{binding examplecommand}"/> </button> 

in running application, button empty. if simpleviewmodel.examplecommand typed object instead of icommand, test shown label on button expected.

what wrong here? wpf treat objects differently based on declared type of property returned them? can worked around, , other types beside icommand affected?

tostring() declared on object , icommand not object interface. assignable object.

the binding system not, said, differentiate on declared type. default ivalueconverter used in case of conversion string does.

internally framework uses defaultvalueconverter when no user defined converter given. in create method can see why interfaces act differently objects here (look specific check of sourcetype.isinterface):

internal static ivalueconverter create(type sourcetype,                                     type targettype,                                      bool targettosource,                                     databindengine engine) {     typeconverter typeconverter;      type innertype;     bool canconvertto, canconvertfrom;      bool sourceisnullable = false;      bool targetisnullable = false;      // sometimes, no conversion necessary     if (sourcetype == targettype ||         (!targettosource && targettype.isassignablefrom(sourcetype)))     {          return valueconverternotneeded;     }       // type convert system.object useless.  claims can     // convert string, throws exception when asked      // so.  work around it.     if (targettype == typeof(object))     {         // sourcetype here might nullable type: consider using          // nullableconverter when appropriate. (uncomment following lines)         //type innertype = nullable.getunderlyingtype(sourcetype);          //if (innertype != null)          //{         //    return new nullableconverter(new objecttargetconverter(innertype),          //                                 innertype, targettype, true, false);         //}          //          return new objecttargetconverter(sourcetype, engine);     }      else if (sourcetype == typeof(object))      {         // targettype here might nullable type: consider using          // nullableconverter when appropriate. (uncomment following lines)         //type innertype = nullable.getunderlyingtype(targettype);         // if (innertype != null)         // {          //     return new nullableconverter(new objectsourceconverter(innertype),         //                                  sourcetype, innertype, false, true);          // }           //          return new objectsourceconverter(targettype, engine);     }      // use system.convert well-known base types      if (systemconvertconverter.canconvert(sourcetype, targettype))     {          return new systemconvertconverter(sourcetype, targettype);      }      // need check nullable types first, since nullableconverter bit over-eager;     // typeconverter nullable can convert e.g. nullable<datetime> string     // ends doing different conversion typeconverter     // generic's inner type, e.g. bug 1361977      innertype = nullable.getunderlyingtype(sourcetype);     if (innertype != null)      {          sourcetype = innertype;         sourceisnullable = true;      }     innertype = nullable.getunderlyingtype(targettype);     if (innertype != null)     {          targettype = innertype;         targetisnullable = true;      }      if (sourceisnullable || targetisnullable)     {          // single-level recursive call try find converter basic value types         return create(sourcetype, targettype, targettosource, engine);     }      // special case converting ilistsource ilist     if (typeof(ilistsource).isassignablefrom(sourcetype) &&          targettype.isassignablefrom(typeof(ilist)))      {         return new listsourceconverter();      }      // interfaces best handled on per-instance basis.  type may     // not implement interface, instance of derived type may.      if (sourcetype.isinterface || targettype.isinterface)     {          return new interfaceconverter(sourcetype, targettype);      }      // try using source's type converter     typeconverter = getconverter(sourcetype);     canconvertto = (typeconverter != null) ? typeconverter.canconvertto(targettype) : false;     canconvertfrom = (typeconverter != null) ? typeconverter.canconvertfrom(targettype) : false;       if ((canconvertto || targettype.isassignablefrom(sourcetype)) &&          (!targettosource || canconvertfrom || sourcetype.isassignablefrom(targettype)))      {         return new sourcedefaultvalueconverter(typeconverter, sourcetype, targettype,                                                 targettosource && canconvertfrom, canconvertto, engine);     }      // if doesn't work, try using target's type converter      typeconverter = getconverter(targettype);     canconvertto = (typeconverter != null) ? typeconverter.canconvertto(sourcetype) : false;      canconvertfrom = (typeconverter != null) ? typeconverter.canconvertfrom(sourcetype) : false;       if ((canconvertfrom || targettype.isassignablefrom(sourcetype)) &&          (!targettosource || canconvertto || sourcetype.isassignablefrom(targettype)))     {         return new targetdefaultvalueconverter(typeconverter, sourcetype, targettype,                                                canconvertfrom, targettosource && canconvertto, engine);      }      // nothing worked, give      return null; }  

according documentation should provide user defined ivalueconverter when binding property of different type dependency property binding relying on tostring being called implementation detail of frameworks default conversion mechanism (and undocumented far know, states default , fallback values defined circumstances) , change @ moment.


Comments

Popular posts from this blog

php - Calling a template part from a post -

Firefox SVG shape not printing when it has stroke -

How to mention the localhost in android -