c# - Making a colorable image - changing the image's source in code behind messes up events -
c# - Making a colorable image - changing the image's source in code behind messes up events -
i'm trying create colorableimage
custom control, not sure if trying possible. class rather straightforward:
public class colorableimage : image { private bool changedbycolor { get; set; } public static readonly dependencyproperty colorproperty; public static readonly dependencyproperty uncoloredsourceproperty; static colorableimage() { defaultstylekeyproperty.overridemetadata(typeof(colorableimage), new frameworkpropertymetadata(typeof(colorableimage))); sourceproperty.overridemetadata(typeof(colorableimage), new frameworkpropertymetadata(new propertychangedcallback(sourcechanged))); colorproperty = dependencyproperty.register("color", typeof(color), typeof(colorableimage), new frameworkpropertymetadata(new propertychangedcallback(colorchanged))); uncoloredsourceproperty = dependencyproperty.register("uncoloredsource", typeof(imagesource), typeof(colorableimage)); } public color color { { homecoming (color)getvalue(colorproperty); } set { setvalue(colorproperty, value); } } public imagesource uncoloredsource { { homecoming (imagesource)getvalue(uncoloredsourceproperty); } protected set { setvalue(uncoloredsourceproperty, value); } } private static void sourcechanged(dependencyobject d, dependencypropertychangedeventargs e) { colorableimage cimg = (colorableimage)d; if (!cimg.changedbycolor) { cimg.uncoloredsource = cimg.source; if (cimg.color != null && !cimg.color.tostring().equals("#00000000")) { colorchanged(d, e); } } } private static void colorchanged(dependencyobject d, dependencypropertychangedeventargs e) { colorableimage cimg = (colorableimage)d; // phone call sourcechanged don't want (since alter uncoloredimage) cimg.changedbycolor = true; cimg.source = colorsource(cimg.source, cimg.color); cimg.changedbycolor = false; } private static imagesource colorsource(imagesource source, color color) { bitmapsource bitmapsource = (bitmapsource)source; if (bitmapsource.format.bitsperpixel != 32 && bitmapsource.format != system.windows.media.pixelformats.bgra32) { bitmapsource = new formatconvertedbitmap(bitmapsource, system.windows.media.pixelformats.bgra32, null, 0); } writeablebitmap wbmp = new writeablebitmap(bitmapsource); // necessary image info re-create pixel array var bytesperpixel = (wbmp.format.bitsperpixel + 7) / 8; var stride = wbmp.pixelwidth * bytesperpixel; var arraysize = stride * wbmp.pixelheight; // re-create image pixel array var pixelarray = new byte[arraysize]; wbmp.copypixels(pixelarray, stride, 0); // convert system.windows.media.color system.drawing.color system.drawing.color newcolor = system.drawing.color.fromargb(color.a, color.r, color.g, color.b); // set new pixels pixel array (int = 0; < pixelarray.length; += bytesperpixel) { // color pixels have no transparency // simple alogirthm; can pretty much have 1 color in image, rest of beingness transparent; meant small, simple icons if (pixelarray[i + 3] == 255) { pixelarray[i] = newcolor.b; pixelarray[i + 1] = newcolor.g; pixelarray[i + 2] = newcolor.r; pixelarray[i + 3] = newcolor.a; } } // remake image wbmp.writepixels(new int32rect(0, 0, wbmp.pixelwidth, wbmp.pixelheight), pixelarray, stride, 0); homecoming wbmp; } }
the coloring algorithm simple , thought able replace every pixel not transparent given color
, dependency property on control. there read-only property on command called uncoloredsource
give original image source, since actual source
has changed due coloring.
however, think doing breaking kind of internal binding image
command has on source
property. testing listviewitems
follows:
<controltemplate x:key="listboxitemcontroltemplate1" targettype="{x:type listboxitem}"> <local:colorableimage x:name="img" source="plus-black.png" color="red"></local:colorableimage> <controltemplate.triggers> <trigger property="isselected" value="true"> <setter targetname="img" property="color" value="blue" /> <setter targetname="img" property="source" value="minus-black.png" /> </trigger> </controltemplate.triggers> </controltemplate> ... <listview> <listviewitem template="{dynamicresource listboxitemcontroltemplate1}" /> <listviewitem template="{dynamicresource listboxitemcontroltemplate1}" /> <listviewitem template="{dynamicresource listboxitemcontroltemplate1}" /> </listview>
the image changes color successfully, i've found sourcechanged
event never fires 1 time again after color
changed. guess because reassigning source
property in code-behind in colorchanged
, messes trigger... kind of surprised mess up.
also, if switch around trigger little bit, confirms think happening. if set no initial color, , in trigger alter source
first , color
second, source , color change, when select sec list item, previous list item disappears completely, , when select third, sec disappears completely, etc., think means trigger can no longer access old source revert (unsure why).
c# wpf
Comments
Post a Comment