i create rangeslider control: xaml:
<style x:key="rangesliderrepeatbutton" targettype="{x:type repeatbutton}"> <setter property="snapstodevicepixels" value="true" /> <setter property="overridesdefaultstyle" value="true" /> <setter property="template"> <setter.value> <controltemplate targettype="{x:type repeatbutton}"> <border background="transparent" height="6" /> </controltemplate> </setter.value> </setter> </style> <style x:key="rangesliderthumbstyle" targettype="{x:type thumb}"> <setter property="snapstodevicepixels" value="true" /> <setter property="overridesdefaultstyle" value="true" /> <setter property="verticalalignment" value="center" /> <setter property="template"> <setter.value> <controltemplate targettype="thumb"> <grid margin="0,0,0,10"> <label x:name="part_valueofslider" content="{binding value, relativesource={relativesource ancestortype={x:type slider}}}" margin="0 -20 0 0" horizontalalignment="center" foreground="red"/> <path x:name="part_rectangle" fill="gray"> <path.data> <rectanglegeometry rect="0,0 10 9" radiusx="2" radiusy="2"></rectanglegeometry> </path.data> <path.effect> <dropshadoweffect shadowdepth="2" blurradius="3" color="black" opacity="0.4" direction="270" /> </path.effect> </path> <path x:name="part_traingle" data="m 0 8 l 5 14 l 10 8 z" fill="gray" > <path.effect> <dropshadoweffect shadowdepth="1" blurradius="0" color="black" opacity="0.4" direction="270" /> </path.effect> </path> </grid> <controltemplate.triggers> <trigger property="ismouseover" value="true"> <setter targetname="part_rectangle" property="fill" value="{dynamicresource labledsliderthumbhoverbrush}" /> <setter targetname="part_traingle" property="fill" value="{dynamicresource labledsliderthumbhoverbrush}" /> </trigger> <trigger property="ismousecaptured" value="true"> <setter targetname="part_rectangle" property="fill" value="{dynamicresource labledsliderthumbfocusesbrush}" /> <setter targetname="part_traingle" property="fill" value="{dynamicresource labledsliderthumbfocusesbrush}" /> </trigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> <style x:key="rangeslider" targettype="{x:type slider}"> <setter property="focusable" value="false"/> <setter property="snapstodevicepixels" value="true" /> <setter property="overridesdefaultstyle" value="true" /> <setter property="template"> <setter.value> <controltemplate targettype="{x:type slider}"> <grid> <grid.rowdefinitions> <rowdefinition height="30" /> </grid.rowdefinitions> <grid.columndefinitions> <columndefinition width="*" minwidth="{templatebinding minwidth}"/> <columndefinition width="auto"/> <columndefinition width="auto"/> </grid.columndefinitions> <track grid.column="0" x:name="part_track"> <track.decreaserepeatbutton> <repeatbutton style="{staticresource rangesliderrepeatbutton}" command="slider.decreaselarge" /> </track.decreaserepeatbutton> <track.thumb> <thumb x:name="part_thumb" style="{staticresource rangesliderthumbstyle}"/> </track.thumb> <track.increaserepeatbutton> <repeatbutton style="{staticresource rangesliderrepeatbutton}" command="slider.increaselarge" /> </track.increaserepeatbutton> </track> </grid> </controltemplate> </setter.value> </setter> </style> <grid x:name="layoutroot" background="#ff878889"> <grid.columndefinitions> <columndefinition width="47*"/> <columndefinition width="353*"/> </grid.columndefinitions> <border verticalalignment="center" borderbrush="black" background="black" height="10" grid.column="0" borderthickness="1" padding="2" cornerradius="4" grid.columnspan="2" margin="0,5"/> <border x:name="progressborder" snapstodevicepixels="true" background="blue" borderbrush="blue" height="6" verticalalignment="center" grid.columnspan="2" margin="0,7" /> <slider x:name="lowerslider" minimum="{binding relativesource={relativesource ancestortype=local:rangeslider}, path=minimum, mode=twoway}" maximum="{binding relativesource={relativesource ancestortype=local:rangeslider}, path=maximum, mode=twoway}" value="{binding relativesource={relativesource ancestortype=local:rangeslider}, path=lowervalue, mode=twoway}" style="{staticresource sliderstyle}" grid.columnspan="2" /> <slider x:name="upperslider" minimum="{binding relativesource={relativesource ancestortype=local:rangeslider}, path=minimum, mode=twoway}" maximum="{binding relativesource={relativesource ancestortype=local:rangeslider}, path=maximum, mode=twoway}" value="{binding relativesource={relativesource ancestortype=local:rangeslider}, path=uppervalue, mode=twoway}" style="{staticresource sliderstyle}" grid.column="1" /> </grid>
rangeslider.cs
public partial class rangeslider : usercontrol { public rangeslider() { this.initializecomponent(); this.layoutupdated += new eventhandler(rangeslider_layoutupdated); } void rangeslider_layoutupdated(object sender, eventargs e) { setprogressborder(); } private void setprogressborder() { double lowerpoint = (this.actualwidth * (lowervalue - minimum)) / (maximum - minimum); double upperpoint = (this.actualwidth * (uppervalue - minimum)) / (maximum - minimum); upperpoint = this.actualwidth - upperpoint; progressborder.margin = new thickness(lowerpoint, 0, upperpoint, 0); } public double minimum { { return (double)getvalue(minimumproperty); } set { setvalue(minimumproperty, value); } } public double maximum { { return (double)getvalue(maximumproperty); } set { setvalue(maximumproperty, value); } } public double lowervalue { { return (double)getvalue(lowervalueproperty); } set { setvalue(lowervalueproperty, value); } } public double uppervalue { { return (double)getvalue(uppervalueproperty); } set { setvalue(uppervalueproperty, value); } } public static readonly dependencyproperty minimumproperty = dependencyproperty.register("minimum", typeof(double), typeof(rangeslider), new uipropertymetadata(0d, new propertychangedcallback(propertychanged))); public static readonly dependencyproperty lowervalueproperty = dependencyproperty.register("lowervalue", typeof(double), typeof(rangeslider), new uipropertymetadata(10d, new propertychangedcallback(propertychanged))); public static readonly dependencyproperty uppervalueproperty = dependencyproperty.register("uppervalue", typeof(double), typeof(rangeslider), new uipropertymetadata(90d, new propertychangedcallback(propertychanged))); public static readonly dependencyproperty maximumproperty = dependencyproperty.register("maximum", typeof(double), typeof(rangeslider), new uipropertymetadata(100d, new propertychangedcallback(propertychanged))); private static void propertychanged(dependencyobject d, dependencypropertychangedeventargs e) { rangeslider slider = (rangeslider)d; if (e.property == rangeslider.lowervalueproperty) { slider.upperslider.value = math.max(slider.upperslider.value, slider.lowerslider.value); } else if (e.property == rangeslider.uppervalueproperty) { slider.lowerslider.value = math.min(slider.upperslider.value, slider.lowerslider.value); } slider.setprogressborder(); } }
it work fine when label x:name="part_valueofslider"
contain small value.
when label x:name="part_valueofslider"
has big value, progressborder display show not expected
how set progressborder work fine? me !!!
i using 1 slider work fine me xaml code slider
<controltemplate x:key="timerangeslidertemplate" targettype="{x:type slider}"> <stackpanel> <border snapstodevicepixels="true" borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}"> <grid> <grid.rowdefinitions> <rowdefinition height="auto"/> <rowdefinition height="auto" minheight="{templatebinding minheight}"/> <rowdefinition height="auto"/> </grid.rowdefinitions> <rectangle x:name="part_selectionrange"/> <track x:name="part_track" grid.row="1"> <track.thumb> <thumb x:name="thumb"> <thumb.template> <controltemplate targettype="thumb"> <rectangle fill="red" stroke="black" strokethickness="1" width="10" height="18" snapstodevicepixels="true"/> </controltemplate> </thumb.template> </thumb> </track.thumb> </track> </grid> </border> </stackpanel> </controltemplate> <style targettype="{x:type sliders:timerangeslider}"> <setter property="template"> <setter.value> <controltemplate targettype="{x:type sliders:timerangeslider}"> <grid verticalalignment="top"> <grid.rowdefinitions> <rowdefinition height="auto"/> <rowdefinition height="auto"/> </grid.rowdefinitions> <stackpanel orientation="horizontal"> <textblock text="{binding elementname=part_lowerslider,path=value}" foreground="red" verticalalignment="top" margin="{binding elementname=part_selectedrect,path=margin}"/> <textblock x:name="part_rightthumpvalue" text="{binding elementname=part_upperslider,path=value}" foreground="red" verticalalignment="top" horizontalalignment="left"/> </stackpanel> <grid grid.row="1"> <border borderthickness="0,1,0,0" borderbrush="black" verticalalignment="center" height="1" margin="5,0,5,0"/> <rectangle x:name="part_selectedrect" fill="green" height="10" horizontalalignment="left"/> <slider x:name="part_lowerslider" minimum="{templatebinding minimum}" maximum="{templatebinding maximum}" value="{templatebinding lowervalue}" template="{staticresource timerangeslidertemplate}" margin="0,0,0,0"/> <slider x:name="part_upperslider" minimum="{templatebinding minimum}" maximum="{templatebinding maximum}" value="{templatebinding uppervalue}" template="{staticresource timerangeslidertemplate}" margin="0,0,0,0"/> </grid> </grid> </controltemplate> </setter.value> </setter> </style>
and here cs file of xaml
public class timerangeslider : control { private const string partname_lowerslider = "part_lowerslider"; private const string partname_upperslider = "part_upperslider"; private const string partname_selectedregion = "part_selectedrect"; private const string part_rightthumpvalue = "part_rightthumpvalue"; private slider lowerslider; private slider upperslider; rectangle selectedrect; textblock righttext; public timerangeslider() { this.defaultstylekey = typeof(timerangeslider); this.loaded += timerangeslider_loaded; } void timerangeslider_loaded(object sender, routedeventargs e) { lowerslider.valuechanged += lowerslider_valuechanged; upperslider.valuechanged += upperslider_valuechanged; lowerslider.minimum = minimum; lowerslider.maximum = maximum; lowerslider.value = lowervalue; upperslider.minimum = minimum; upperslider.maximum = maximum; upperslider.value = uppervalue; setview(); } public override void onapplytemplate() { lowerslider = this.gettemplatechild(partname_lowerslider) slider; upperslider = this.gettemplatechild(partname_upperslider) slider; selectedrect = this.gettemplatechild(partname_selectedregion) rectangle; righttext = this.gettemplatechild(part_rightthumpvalue) textblock; base.onapplytemplate(); } private void lowerslider_valuechanged(object sender, routedpropertychangedeventargs<double> e) { upperslider.value = math.max(upperslider.value, lowerslider.value); setview(); } private void upperslider_valuechanged(object sender, routedpropertychangedeventargs<double> e) { lowerslider.value = math.min(upperslider.value, lowerslider.value); setview(); } private void setview() { lowervalue = lowerslider.value; uppervalue = upperslider.value; var unit = lowerslider.actualwidth / maximum; var leftmargin = lowervalue * unit; if (uppervalue > lowervalue) { var width = (uppervalue - lowervalue) * unit; selectedrect.width = width; } selectedrect.margin = new thickness(leftmargin, 0, 0, 0); righttext.margin = new thickness(selectedrect.width-20, 0, 0, 0); } public double minimum { { return (double)getvalue(minimumproperty); } set { setvalue(minimumproperty, value); } } public static readonly dependencyproperty minimumproperty = dependencyproperty.register("minimum", typeof(double), typeof(timerangeslider), new uipropertymetadata(0d)); public double lowervalue { { return (double)getvalue(lowervalueproperty); } set { setvalue(lowervalueproperty, value); } } public static readonly dependencyproperty lowervalueproperty = dependencyproperty.register("lowervalue", typeof(double), typeof(timerangeslider), new uipropertymetadata(0d)); public double uppervalue { { return (double)getvalue(uppervalueproperty); } set { setvalue(uppervalueproperty, value); } } public static readonly dependencyproperty uppervalueproperty = dependencyproperty.register("uppervalue", typeof(double), typeof(timerangeslider), new uipropertymetadata(0d)); public double maximum { { return (double)getvalue(maximumproperty); } set { setvalue(maximumproperty, value); } } public static readonly dependencyproperty maximumproperty = dependencyproperty.register("maximum", typeof(double), typeof(timerangeslider), new uipropertymetadata(1d)); }
and usage of control
<slidercontrol:timerangeslider x:name="slider" margin="10" lowervalue="30" uppervalue="70" minimum="0" maximum="100" />
Comments
Post a Comment