Tuesday, 15 September 2015

resize - WPF Scrollviewer DesiredSize does not increase when ScrollBar gets Visible -



resize - WPF Scrollviewer DesiredSize does not increase when ScrollBar gets Visible -

i have wpf usercontrol (inside elementhost) scrollviewer contains itemscontrol . horizontalscrollbarvisibility set auto, if no scrolling necessary, scrollbargets hidden.

my requirement is, if scrollbar gets shown/hidden, elementhost adjust it's height accordingly. accomplish that, i'm listening sizechanged event, desiredsize of scrollviewer in eventhandler, pass desiredsize.height elementhost.

2. 3.

one way, works: scrollbar visible (situation 1), enlarge window until items of itemscontrol visible, scrollbar disappears, elementhost adjusts reduced height (situation 2). desiredsize got smaller moment scrollbar hidden.

the other way, though, doesn't work: scrollbar not visible (situation 2), cut down window size until scrollbar necessary , appears. desiredsize stays same, , elementhost not adjust (situation 3).

any ideas?

this xaml of scrollviewer, mvvm stuff, don't hung on this, point is, why desiredsize not increment when scrollbar appears? why shrink only?

<scrollviewer horizontalscrollbarvisibility="auto" verticalscrollbarvisibility="hidden" > <i:interaction.behaviors> <beh:heightchangedbehavior heightchangedcommand="{binding heightchangedcommand}" /> </i:interaction.behaviors> <itemscontrol itemssource="{binding tabheaders}" > <itemscontrol.itemspanel> <itemspaneltemplate> <stackpanel isitemshost="true" orientation="horizontal"/> </itemspaneltemplate> </itemscontrol.itemspanel> <itemscontrol.itemtemplate> <datatemplate datatype="models:tabheaderbuttonmodel"> <radiobutton content="{binding caption}" ischecked="{binding ischecked, mode=twoway}" groupname="tabs" command="{binding selectionchangedcommand}" commandparameter="{binding}" style="{staticresource tabheadertogglebuttonstyle}"> </radiobutton> </datatemplate> </itemscontrol.itemtemplate> </itemscontrol> </scrollviewer>

scrollviewer style (basically default wpf):

<style x:key="scrollviewerstyle1" targettype="{x:type scrollviewer}"> <setter property="template" > <setter.value> <controltemplate targettype="{x:type scrollviewer}"> <grid x:name="grid" background="{templatebinding background}"> <grid.columndefinitions> <columndefinition width="*"/> <columndefinition width="auto"/> </grid.columndefinitions> <grid.rowdefinitions> <rowdefinition height="*"/> <rowdefinition height="auto"/> </grid.rowdefinitions> <rectangle x:name="corner" grid.column="1" fill="{dynamicresource {x:static systemcolors.controlbrushkey}}" grid.row="1"/> <scrollcontentpresenter x:name="part_scrollcontentpresenter" cancontentscroll="{templatebinding cancontentscroll}" canhorizontallyscroll="false" canverticallyscroll="false" contenttemplate="{templatebinding contenttemplate}" content="{templatebinding content}" grid.column="0" margin="{templatebinding padding}" grid.row="0"/> <scrollbar x:name="part_verticalscrollbar" automationproperties.automationid="verticalscrollbar" cursor="arrow" grid.column="1" maximum="{templatebinding scrollableheight}" minimum="0" grid.row="0" visibility="{templatebinding computedverticalscrollbarvisibility}" value="{binding verticaloffset, mode=oneway, relativesource={relativesource templatedparent}}" viewportsize="{templatebinding viewportheight}"/> <scrollbar x:name="part_horizontalscrollbar" automationproperties.automationid="horizontalscrollbar" cursor="arrow" grid.column="0" maximum="{templatebinding scrollablewidth}" minimum="0" orientation="horizontal" grid.row="1" visibility="{templatebinding computedhorizontalscrollbarvisibility}" value="{binding horizontaloffset, mode=oneway, relativesource={relativesource templatedparent}}" viewportsize="{templatebinding viewportwidth}" style="{dynamicresource scrollbarstyle1}"/> </grid> </controltemplate> </setter.value> </setter> <style.triggers> <trigger property="isenabled" value="false"> <setter property="foreground" value="white"/> </trigger> </style.triggers> </style>

i had calculate desired height getting scrollviewer's content desired height , adding scrollbar height if visible.

this still feels awkward me, if have improve solution, i'll gladly alter accepted answer.

public class heightchangedbehavior : behavior<scrollviewer> { public icommand heightchangedcommand { { homecoming (icommand)getvalue(heightchangedcommandproperty); } set { setvalue(heightchangedcommandproperty, value); } } public static readonly dependencyproperty heightchangedcommandproperty = dependencyproperty.register("heightchangedcommand", typeof(icommand), typeof(heightchangedbehavior), new propertymetadata(null)); protected override void onattached() { this.associatedobject.scrollchanged += associatedobject_scrollchanged; base.onattached(); } /// <summary> /// calculates desired height scrollviewer, sum of content /// desired height and, if visible, horizontal scrollbar height. /// </summary> void associatedobject_scrollchanged(object sender, scrollchangedeventargs e) { scrollviewer sv = (scrollviewer)sender; // content height double height = ((frameworkelement)sv.content).desiredsize.height; if (sv.computedhorizontalscrollbarvisibility == visibility.visible) { // add together scrollbar height height += (double)sv.findresource(systemparameters.horizontalscrollbarheightkey); // template of scrollbar should utilize key } int intheight = (int)math.ceiling(height); // whole pixels // execute command icommand cmd = this.heightchangedcommand; if (cmd != null && intheight != sv.actualheight) cmd.execute(intheight); } }

wpf resize scrollbar scrollviewer elementhost

No comments:

Post a Comment