c# - Binding properties (width/sorting) of DataGrid on dynamic TabPage -
i've created little wpf test project demonstrate question. project contains single wpf window. window contains tabcontrol
. pages of tabcontrol
created dynamically bound itemsource
.
so here xaml:
<window x:name="window" x:class="testwpf.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:testwpf" title="mainwindow" height="350" width="525"> <tabcontrol x:name="tabcontrol" borderthickness="0" itemssource ="{binding medialists, elementname=window, notifyonsourceupdated=true}"> <tabcontrol.itemtemplate> <datatemplate datatype="{x:type vm:medialist}"> <textblock padding="2" text="{binding mediatypename}" horizontalalignment="center" verticalalignment="center"/> </datatemplate> </tabcontrol.itemtemplate> <tabcontrol.contenttemplate> <datatemplate x:name="contenttemplate" datatype="{x:type vm:medialist}"> <datagrid x:name="dgmedialist" itemssource="{binding medias, bindsdirectlytosource=true}" dockpanel.dock="top" autogeneratecolumns="false" horizontalgridlinesbrush="{dynamicresource {x:static systemcolors.activeborderbrushkey}}" verticalgridlinesbrush="{dynamicresource {x:static systemcolors.activeborderbrushkey}}"> <datagrid.columns> <datagridtextcolumn x:name="clmauthor" header="author" binding="{binding author}" isreadonly="true" canuserreorder="false" /> <datagridtextcolumn x:name="clmtitle" header="title" binding="{binding title}" isreadonly="true" canuserreorder="false" /> </datagrid.columns> </datagrid> </datatemplate> </tabcontrol.contenttemplate> </tabcontrol> </window>
and code behind this:
public partial class mainwindow : window { private readonly observablecollection<medialist> m_medialists = new observablecollection<medialist>(); public observablecollection<medialist> medialists { { return m_medialists; } } public mainwindow() { initializecomponent(); medialist cdlist = new medialist("cds"); cdlist.medias.add(new media("authorcda", "titlecda1")); cdlist.medias.add(new media("authorcda", "titlecda2")); cdlist.medias.add(new media("authorcdb", "titlecdb1")); cdlist.medias.add(new media("authorcdb", "titlecdb2")); medialist booklist = new medialist("books"); booklist.medias.add(new media("authorbooka", "titlebooka1")); booklist.medias.add(new media("authorbooka", "titlebooka2")); booklist.medias.add(new media("authorbookb", "titlebookb1")); booklist.medias.add(new media("authorbookb", "titlebookb2")); m_medialists.add(cdlist); m_medialists.add(booklist); } }
with medialist
this:
public class medialist : inotifypropertychanged { public event propertychangedeventhandler propertychanged; protected virtual void onpropertychanged(string propertyname) { propertychangedeventhandler handler = propertychanged; if (handler != null) handler(this, new propertychangedeventargs(propertyname)); } private readonly observablecollection<media> m_medias = new observablecollection<media>(); public string mediatypename { get; private set; } public observablecollection<media> medias { { return m_medias; }} public medialist(string typename) { mediatypename = typename; } }
and media
this:
public class media { public string author { get; private set; } public string title { get; private set; } public media(string author, string title) { author = author; title = title; } }
so works fine can see here:
now problem: how save datagrid
's layout each tabpage
? when switch between tabpage
s, column width kept same pages, sorting lost completely.
i want bind column widths of datagrid
multi-column sort settings changed user in members of medialist
instance.
so keep question short, let's concentrate on column widths. added members medialist
class:
private datagridlength m_widthauthor = datagridlength.sizetocells; private datagridlength m_widthtitle = datagridlength.sizetocells; public datagridlength widthauthor { { return m_widthauthor; } set { if (value == m_widthauthor) return; m_widthauthor = value; onpropertychanged("widthauthor"); } } public datagridlength widthtitle { { return m_widthtitle; } set { if (value == m_widthtitle) return; m_widthtitle = value; onpropertychanged("widthtitle"); } }
and tried set binding in xaml:
<datagridtextcolumn x:name="clmauthor" ... width="{binding widthauthor, mode=twoway, notifyonsourceupdated=true, updatesourcetrigger=propertychanged}" /> <datagridtextcolumn x:name="clmtitle" ... width="{binding widthtitle, mode=twoway, notifyonsourceupdated=true, updatesourcetrigger=propertychanged}" />
but unfortunatly, doesn't work. i've read on several articles two-way binding difficult. one-way binding won't work me. (i'm pretty new wpf/mvvm, maybe use wrong words here...)
in debugger output window can see these error message width-bindings:
system.windows.data error: 2 : cannot find governing frameworkelement or frameworkcontentelement target element. bindingexpression:path=widthauthor; dataitem=null; target element 'datagridtextcolumn' (hashcode=54916642); target property 'width' (type 'datagridlength') system.windows.data error: 2 : cannot find governing frameworkelement or frameworkcontentelement target element. bindingexpression:path=widthtitle; dataitem=null; target element 'datagridtextcolumn' (hashcode=40809782); target property 'width' (type 'datagridlength')
so if can tell me how save datagrid
properties each tabpage
happy. focus of question on widths. sorting may subject of new question (note binding sortdirection
of columns won't work multi-column sort)
edit: i've added diag:presentationtracesources.tracelevel=high
binding
expression 1 of columns width
, found these messages in debug output:
system.windows.data warning: 62 : bindingexpression (hash=18270086): attach system.windows.controls.datagridtextcolumn.width (hash=37671782) system.windows.data warning: 64 : bindingexpression (hash=18270086): use framework mentor <null> system.windows.data warning: 67 : bindingexpression (hash=18270086): resolving source system.windows.data warning: 69 : bindingexpression (hash=18270086): framework mentor not found system.windows.data warning: 65 : bindingexpression (hash=18270086): resolve source deferred
i'm new wpf understand framework mentor
, if should null
.
i solved of this article. unfortunately wpf knowledge still low cannot explain (as author of mentioned article) happens behind scenes , if solution.
so here did:
implementing `bindingproxy` inherited `freezable`
one of problems datacontext
not inherited datagridtextcolumn
. aim store in proxy.
public class bindingproxy : freezable { protected override freezable createinstancecore() { return new bindingproxy(); } public object data { { return getvalue(data_property); } set { setvalue(data_property, value); } } // using dependencyproperty backing store data. enables animation, styling, binding, etc... public static readonly dependencyproperty data_property = dependencyproperty.register("data", typeof(object), typeof(bindingproxy), new uipropertymetadata(null)); }
declaring instance of `bindingproxy` local resource in `datagrid`
i added local resource datagrid
in xaml:
<datagrid.resources> <vm:bindingproxy x:key="proxy" data="{binding}" /> </datagrid.resources>
adjusting binding
at last modify binding expression datagridtextcolum
's width:
width="{binding data.widthauthor, source={staticresource proxy}....
et voilá, works!
i continue research on how multi-column sort. if can't find solution open new question. if no 1 adds solution in next days, accept own answer.
update: solved multi-column sort problem here.
Comments
Post a Comment