Sunday, 15 March 2015

gridview - WPF: Scroll Itemcontrol Content Fixed Header -



gridview - WPF: Scroll Itemcontrol Content Fixed Header -

is possible wpf's itemscontrol: demo

i trying freeze groupeditems rather gridview columns.

resources:

<window.resources> <collectionviewsource x:key="data" source="{binding}"> <collectionviewsource.groupdescriptions> <propertygroupdescription propertyname="date"/> </collectionviewsource.groupdescriptions> </collectionviewsource> </window.resources>

listview:

<listview grid.column="0" itemssource="{binding source={staticresource data}}"> <listview.view> <gridview> <gridview.columns> <gridviewcolumn header="col 1" displaymemberbinding="{binding col1}" width="100"/> <gridviewcolumn header="col 2" displaymemberbinding="{binding col2}" width="100"/> <gridviewcolumn header="col 3" displaymemberbinding="{binding col3}" width="100"/> </gridview.columns> </gridview> </listview.view> <listview.groupstyle> <groupstyle> <groupstyle.containerstyle> <style targettype="{x:type groupitem}"> <setter property="template"> <setter.value> <controltemplate targettype="{x:type groupitem}"> <grid> <grid.rowdefinitions> <rowdefinition height="auto"/> <rowdefinition height="auto"/> </grid.rowdefinitions> <grid grid.row="0"> <grid.columndefinitions> <columndefinition width="*"/> </grid.columndefinitions> <textblock background="beige" fontweight="bold" text="{binding path=name, stringformat={}{0}}"/> </grid> <dockpanel grid.row="1"> <itemspresenter grid.row="2"></itemspresenter> </dockpanel> </grid> </controltemplate> </setter.value> </setter> </style> </groupstyle.containerstyle> </groupstyle> </listview.groupstyle> </listview>

code behind:

public mainwindow() { initializecomponent(); list<string> collist1 = new list<string>(){"item1", "item2", "item3", "item4", "item5", "item6", "item7"}; list<string> collist2 = new list<string>(){"1", "2", "3", "4", "5", "6"}; observablecollection<data> datacollection = new observablecollection<data>(); (var = 0; a<100; a++){ random rnd = new random(); int min = rnd.next(5000); int rnd1 = rnd.next(0, 6); int rnd2 = rnd.next(0, 5); datacollection .add( new data(){ date = datetime.now.addminutes(min).tostring("hh:mm tt"), col1= collist1[rnd2], col2= string.format("col2: {0}", "x"), col3= collist2[rnd2] } ); } this.datacontext = datacollection; } public class info { public string date { get; set; } public string col1{ get; set; } public string col2{ get; set; } public string col3{ get; set; } }

my solution uses textblock overlay shares grouping header style. positioning , right hittesting tricky part, i'm quite confident not break little changes in layout or logic.

i not sure if want hide columnheader or not, easy , doesn't need other adjustments depicted here.

code behind:

using system; using system.collections.generic; using system.collections.objectmodel; using system.windows; using system.windows.controls; using system.windows.media; namespace wpfapplication1 { public partial class freezinggroupheader : usercontrol { private double _listviewheaderheight; private double _listviewsidemargin; public freezinggroupheader() { initializecomponent(); list<string> collist1 = new list<string>() { "item1", "item2", "item3", "item4", "item5", "item6", "item7" }; list<string> collist2 = new list<string>() { "1", "2", "3", "4", "5", "6" }; observablecollection<data> datacollection = new observablecollection<data>(); random rnd = new random(); (var = 0; < 100; a++) { int min = rnd.next(5000); int rnd1 = rnd.next(0, 6); int rnd2 = rnd.next(0, 5); datacollection.add( new data() { date = datetime.now.addminutes(min).tostring("hh:mm tt"), col1 = collist1[rnd2], col2 = string.format("col2: {0}", "x"), col3 = collist2[rnd2] } ); } this.datacontext = datacollection; this.loaded += onloaded; } private void onloaded(object sender, routedeventargs e) { // position frozen header getlistviewmargins(this.listview1); thickness margin = this.frozengroupheader.margin; margin.top = _listviewheaderheight; margin.right = systemparameters.verticalscrollbarwidth + _listviewsidemargin; margin.left = _listviewsidemargin; this.frozengroupheader.margin = margin; updatefrozengroupheader(); } private void listview1_scrollchanged(object sender, scrollchangedeventargs e) { updatefrozengroupheader(); } /// <summary> /// sets text , visibility of frozen header /// </summary> private void updatefrozengroupheader() { if (listview1.hasitems) { // text of frozengroupheader groupitem grouping = getfirstvisiblegroupitem(this.listview1); if (group != null) { object info = group.content; this.frozengroupheader.text = data.gettype().getproperty("name").getvalue(data, null) string; // slight hack } this.frozengroupheader.visibility = visibility.visible; } else this.frozengroupheader.visibility = visibility.collapsed; } /// <summary> /// sets values used in positioning of frozen header /// </summary> private void getlistviewmargins(listview listview) { if (listview.hasitems) { object o = listview.items[0]; listviewitem firstitem = (listviewitem)listview.itemcontainergenerator.containerfromitem(o); if (firstitem != null) { groupitem grouping = findupvisualtree<groupitem>(firstitem); point p = group.translatepoint(new point(0, 0), listview); _listviewheaderheight = p.y; // height of columnheader _listviewsidemargin = p.x; // listview borders } } } /// <summary> /// gets first visible groupitem in listview /// </summary> private groupitem getfirstvisiblegroupitem(listview listview) { hittestresult hittest = visualtreehelper.hittest(listview, new point(5, _listviewheaderheight + 5)); groupitem grouping = findupvisualtree<groupitem>(hittest.visualhit); homecoming group; } /// <summary> /// walk visual tree find object of type t, starting initial object /// http://www.codeproject.com/tips/75816/walk-up-the-visual-tree /// </summary> private static t findupvisualtree<t>(dependencyobject initial) t : dependencyobject { dependencyobject current = initial; while (current != null && current.gettype() != typeof(t)) { current = visualtreehelper.getparent(current); } homecoming current t; } public class info { public string date { get; set; } public string col1 { get; set; } public string col2 { get; set; } public string col3 { get; set; } } } }

xaml:

<usercontrol x:class="wpfapplication1.freezinggroupheader" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:ignorable="d" d:designheight="300" d:designwidth="300" > <usercontrol.resources> <collectionviewsource x:key="data" source="{binding}"> <collectionviewsource.groupdescriptions> <propertygroupdescription propertyname="date"/> </collectionviewsource.groupdescriptions> </collectionviewsource> <style x:key="groupheaderstyle1" targettype="{x:type textblock}"> <setter property="background" value="beige" /> <setter property="foreground" value="black" /> <setter property="fontweight" value="bold" /> </style> </usercontrol.resources> <grid> <listview x:name="listview1" grid.column="0" itemssource="{binding source={staticresource data}}" scrollviewer.scrollchanged="listview1_scrollchanged" > <listview.view> <gridview> <gridview.columns> <gridviewcolumn header="col 1" displaymemberbinding="{binding col1}" width="100"/> <gridviewcolumn header="col 2" displaymemberbinding="{binding col2}" width="100"/> <gridviewcolumn header="col 3" displaymemberbinding="{binding col3}" width="100"/> </gridview.columns> </gridview> </listview.view> <listview.groupstyle> <groupstyle> <groupstyle.containerstyle> <style targettype="{x:type groupitem}"> <setter property="template"> <setter.value> <controltemplate targettype="{x:type groupitem}"> <grid> <grid.rowdefinitions> <rowdefinition height="auto"/> <rowdefinition height="auto"/> </grid.rowdefinitions> <grid grid.row="0"> <grid.columndefinitions> <columndefinition width="*"/> </grid.columndefinitions> <textblock style="{staticresource groupheaderstyle1}" text="{binding name, stringformat={}{0}}" /> </grid> <dockpanel grid.row="1"> <itemspresenter grid.row="2"></itemspresenter> </dockpanel> </grid> </controltemplate> </setter.value> </setter> </style> </groupstyle.containerstyle> </groupstyle> </listview.groupstyle> </listview> <textblock x:name="frozengroupheader" style="{staticresource groupheaderstyle1}" verticalalignment="top"/> </grid> </usercontrol>

wpf gridview scrollview itemscontrol

No comments:

Post a Comment