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, scrollbar
gets 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
.
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