c# - Sliding text in combobox -
i slide text (marquee text) of selected item in combobox, if it's lenght bigger width of combobox. can either automatical or when user put mouse on combobox. problem have absolutely no idea on how that. it's maybe possible render transform (previous definition of textblock inside it)? or storyboard?
here xaml need modify
<datagrid.columnheaderstyle> <style targettype="{x:type datagridcolumnheader}"> <setter property="contenttemplate" > <setter.value> <datatemplate datatype="datagridcolumnheader" > <combobox itemcontainerstyle="{staticresource singleselectioncomboboxitem}" displaymemberpath="oggetto" width="100" height="20" itemssource="{binding relativesource={relativesource ancestortype={x:type datagrid}},path=datacontext.selezione, updatesourcetrigger=lostfocus}" selectionchanged="singleselectioncombobox_selectionchanged"/> </datatemplate> </setter.value> </setter> </style> </datagrid.columnheaderstyle>
edit: problem don't know properties should target in storyboard
edit2: took template of combobox , modified text box section :
<style x:key="comboboxeditabletextbox" targettype="{x:type textbox}"> <style.triggers> <eventtrigger routedevent="mouseenter"> <eventtrigger.actions> <beginstoryboard> <storyboard> <doubleanimation from="0" to="100" duration="00:00:10" storyboard.targetproperty="x" storyboard.targetname="transfercurreny" repeatbehavior="forever" /> </storyboard> </beginstoryboard> </eventtrigger.actions> </eventtrigger> </style.triggers> <setter property="rendertransform"> <setter.value> <translatetransform x:name="transfercurreny" x="0"/> </setter.value> </setter>
the problem seems have no effect
edit 3: realized had use template use style mentioned above
<controltemplate x:key="comboboxeditabletemplate" targettype="{x:type combobox}"> <grid x:name="placement" snapstodevicepixels="true"> <grid.columndefinitions> <columndefinition width="*" /> <columndefinition width="auto" /> </grid.columndefinitions> <popup x:name="part_popup" allowstransparency="true" grid.columnspan="2" isopen="{binding isdropdownopen, relativesource={relativesource templatedparent}}" popupanimation="{dynamicresource {x:static systemparameters.comboboxpopupanimationkey}}" placement="bottom"> <themes:systemdropshadowchrome x:name="shdw" color="transparent" maxheight="{templatebinding maxdropdownheight}" minwidth="{binding actualwidth, elementname=placement}"> <border x:name="dropdownborder" borderbrush="{dynamicresource {x:static systemcolors.windowframebrushkey}}" borderthickness="1" background="{dynamicresource {x:static systemcolors.windowbrushkey}}"> <scrollviewer x:name="dropdownscrollviewer"> <grid renderoptions.cleartypehint="enabled"> <canvas horizontalalignment="left" height="0" verticalalignment="top" width="0"> <rectangle x:name="opaquerect" fill="{binding background, elementname=dropdownborder}" height="{binding actualheight, elementname=dropdownborder}" width="{binding actualwidth, elementname=dropdownborder}" /> </canvas> <itemspresenter x:name="itemspresenter" keyboardnavigation.directionalnavigation="contained" snapstodevicepixels="{templatebinding snapstodevicepixels}" /> </grid> </scrollviewer> </border> </themes:systemdropshadowchrome> </popup> <themes:listboxchrome x:name="border" borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}" background="{templatebinding background}" grid.columnspan="2" rendermouseover="{templatebinding ismouseover}" renderfocused="{templatebinding iskeyboardfocuswithin}" /> <textbox x:name="part_editabletextbox" horizontalcontentalignment="{templatebinding horizontalcontentalignment}" isreadonly="{binding isreadonly, relativesource={relativesource templatedparent}}" margin="{templatebinding padding}" style="{staticresource comboboxeditabletextbox}" verticalcontentalignment="{templatebinding verticalcontentalignment}" > </textbox> <togglebutton grid.column="1" ischecked="{binding isdropdownopen, mode=twoway, relativesource={relativesource templatedparent}}" style="{staticresource comboboxtogglebutton}" /> </grid> <controltemplate.triggers> <trigger property="iskeyboardfocuswithin" value="true"> <setter property="foreground" value="black" /> </trigger> <trigger property="isdropdownopen" value="true"> <setter property="renderfocused" targetname="border" value="true" /> </trigger> <trigger property="hasitems" value="false"> <setter property="height" targetname="dropdownborder" value="95" /> </trigger> <trigger property="isenabled" value="false"> <setter property="foreground" value="{dynamicresource {x:static systemcolors.graytextbrushkey}}" /> <setter property="background" value="#fff4f4f4" /> </trigger> <multitrigger> <multitrigger.conditions> <condition property="isgrouping" value="true" /> <condition property="virtualizingpanel.isvirtualizingwhengrouping" value="false" /> </multitrigger.conditions> <setter property="scrollviewer.cancontentscroll" value="false" /> </multitrigger> <trigger property="hasdropshadow" sourcename="part_popup" value="true"> <setter property="margin" targetname="shdw" value="0,0,5,5" /> <setter property="color" targetname="shdw" value="#71000000" /> </trigger> <trigger property="scrollviewer.cancontentscroll" sourcename="dropdownscrollviewer" value="false"> <setter property="canvas.top" targetname="opaquerect" value="{binding verticaloffset, elementname=dropdownscrollviewer}" /> <setter property="canvas.left" targetname="opaquerect" value="{binding horizontaloffset, elementname=dropdownscrollviewer}" /> </trigger> </controltemplate.triggers> </controltemplate>
the textbox section 1 use style. when template="{staticresource comboboxeditabletemplate}"
in combobox, cannot see selected item anymore, if it's not null
updated 08/02
basically in order avoid animation issues facing - need add scrollviewer
wrapper content-site or selection-box textblock
. can either using custom template selector combobox
defined below, or provide custom item-template scollviewer
.
secondly, can either create custom combobox
control in c# bind above template-selector/item-template , apply slide-animation on mouseenterevent
; or implement same in xaml itself.
for example - have implemented control in c#, , provided sample usage in xaml.
code custom control, , template selector
public class slidingcombobox : combobox { public static readonly dependencyproperty slideforeverproperty = dependencyproperty.register("slideforever", typeof(bool), typeof(slidingcombobox), new frameworkpropertymetadata(false)); public bool slideforever { { return (bool)getvalue(slideforeverproperty); } set { setvalue(slideforeverproperty, value); } } protected contentpresenter _parent; protected doubleanimation _animation; protected translatetransform _translate; protected storyboard _storyboard; public slidingcombobox() { loaded += excombobox_loaded; cliptobounds = true; //assign template selector - re-template contentsite / selection box //uncomment code - if want default-template popup-items //itemtemplateselector = new slidingcomboboxitemtemplateselector(); } private void excombobox_loaded(object sender, routedeventargs e) { loaded -= excombobox_loaded; //get content-site holder/parent _parent = this.getchildoftype<contentpresenter>(); //setup slide animation _animation = new doubleanimation() { = 0, repeatbehavior = slideforever ? repeatbehavior.forever : new repeatbehavior(1), //repeat if slide-forever true autoreverse = slideforever }; //create storyboard _storyboard = new storyboard(); _storyboard.children.add(_animation); storyboard.settargetproperty(_animation, new propertypath("rendertransform.(translatetransform.x)")); } protected override void onmouseenter(mouseeventargs e) { //get actual textblock renders selected value var textblock = _parent.getchildoftype<textblock>(); //and translate-transform animation textblock.rendertransform = _translate = new translatetransform(); //start animation if text-block width greater parent if (_parent.actualwidth < textblock.actualwidth) { _animation.duration = timespan.frommilliseconds(((int)textblock.text?.length * 100)); _animation.to = _parent.actualwidth - textblock.actualwidth; _storyboard.begin(textblock); } base.onmouseenter(e); } protected override void onmouseleave(mouseeventargs e) { //stop animation once mouse pointer off control _storyboard.stop(); //reset render state var textblock = _parent.getchildoftype<textblock>(); textblock.rendertransform = _translate = new translatetransform(); base.onmouseleave(e); } } public class slidingcomboboxitemtemplateselector : datatemplateselector { datatemplate _selecteditemtemplate; public slidingcomboboxitemtemplateselector() { //create datatemplate scrollviewer , textblock child var textblock = new frameworkelementfactory(typeof(textblock)); textblock.setvalue(textblock.textwrappingproperty, textwrapping.nowrap); textblock.setbinding(textblock.textproperty, new binding("selectedvalue") { relativesource = new relativesource { mode = relativesourcemode.findancestor, ancestortype = typeof(combobox) } }); var scrollviewer = new frameworkelementfactory(typeof(scrollviewer)); scrollviewer.setvalue(scrollviewer.cancontentscrollproperty, true); scrollviewer.setvalue(scrollviewer.horizontalscrollbarvisibilityproperty, scrollbarvisibility.hidden); scrollviewer.setvalue(scrollviewer.verticalscrollbarvisibilityproperty, scrollbarvisibility.disabled); scrollviewer.appendchild(textblock); _selecteditemtemplate = new datatemplate { visualtree = scrollviewer }; } public override datatemplate selecttemplate(object item, dependencyobject container) { comboboxitem comboboxitem = container.getvisualparent<comboboxitem>(); if (comboboxitem == null) { //send if template requested contentsite, , not combo-box item(s) return _selecteditemtemplate; } return null; } } /// <summary> /// visualtree helper /// </summary> public static class helperextensions { public static t getchildoftype<t>(this dependencyobject depobj) t : dependencyobject { if (depobj == null) return null; (int = 0; < visualtreehelper.getchildrencount(depobj); i++) { var child = visualtreehelper.getchild(depobj, i); var result = (child t) ?? getchildoftype<t>(child); if (result != null) return result; } return null; } public static t getvisualparent<t>(this dependencyobject child) t : visual { while ((child != null) && !(child t)) { child = visualtreehelper.getparent(child); } return child t; } }
sample usage:
<window x:class="marqueesample.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:marqueesample" xmlns:sys="clr-namespace:system;assembly=mscorlib" xmlns:col="clr-namespace:system.collections;assembly=mscorlib" mc:ignorable="d" title="mainwindow" height="200" width="400"> <grid margin="20"> <datagrid autogeneratecolumns="false" isreadonly="true" width="225" verticalalignment="center"> <datagrid.itemssource> <col:hashtable> <col:arraylist x:key="testdata1"> <sys:string>tiny</sys:string> <sys:string>keep calm , love programming</sys:string> </col:arraylist> <col:arraylist x:key="testdata2"> <sys:string>sample string</sys:string> <sys:string>another string test</sys:string> </col:arraylist> </col:hashtable> </datagrid.itemssource> <datagrid.columns> <datagridtextcolumn header="name" width="100" binding="{binding key}" /> <datagridtemplatecolumn header="value" width="100"> <datagridtemplatecolumn.celltemplate> <datatemplate> <local:slidingcombobox itemssource="{binding value}"> <local:slidingcombobox.itemtemplate> <datatemplate> <scrollviewer cancontentscroll="true" horizontalscrollbarvisibility="hidden" verticalscrollbarvisibility="disabled"> <textblock text="{binding}" /> </scrollviewer> </datatemplate> </local:slidingcombobox.itemtemplate> </local:slidingcombobox> </datatemplate> </datagridtemplatecolumn.celltemplate> </datagridtemplatecolumn> </datagrid.columns> </datagrid> </grid> </window>
you can use slideforever property manipulate repeatbehaviour.
<local:slidingcombobox itemssource="{binding value}" slideforever="true" />
Comments
Post a Comment