c# - WPF ItemsControl:- Changes Property of Items inside ItemControle after ItemSource Property of ItemsControl being changed at Run-Time -
i have following scenario:
i have used 1 itemscontrol
.
which generates button
per itemssource
given it?
now,
when hitting nextbutton
.[ have mainwindow.xaml ].
the itemssource
of itemscontrol
(pagecontrol) changes
and also have chagne background
of button
have contents equals currentpage
property per scenario.
suppose,
step 1: in click event of button first change itemssource
of itemscontrol
.
step 2: i change background
of particular button. instead of changes in background getting following error.
this operation valid on elements have template applied.
note:- i don’t have problem if directly changes background
without changes in itemssource
.
have @ below code.
mainwindow.xaml
<window x:class="currentpageproblem.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="350" width="525"> <window.resources> <style targettype="button" x:key="buttonstyle"> <setter property="template"> <setter.value> <controltemplate targettype="button"> <border cornerradius="2,2,2,2" horizontalalignment="center" x:name="bordertemplate" background="{templatebinding background}"> <contentpresenter/> </border> <controltemplate.triggers> <trigger property="ismouseover" value="true"> <setter targetname="bordertemplate" property="border.borderbrush" value="gray" /> <setter targetname="bordertemplate" property="border.borderthickness" value="1" /> </trigger> <trigger property="ispressed" value="true"> <setter targetname="bordertemplate" property="border.borderbrush" value="lime" /> </trigger> <trigger property="isfocused" value="true"> <setter targetname="bordertemplate" property="border.background" value="#fd7" /> </trigger> <trigger property="isenabled" value="false"> <setter targetname="bordertemplate" property="border.background" value="lightgray"></setter> </trigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> </window.resources> <grid> <grid.rowdefinitions> <rowdefinition height="47*" /> <rowdefinition height="264*" /> </grid.rowdefinitions> <itemscontrol name="pagecontrol" itemssource="{binding path=pagecollection}" grid.row="0"> <itemscontrol.template> <controltemplate targettype="itemscontrol"> <border > <stackpanel> <itemspresenter></itemspresenter> </stackpanel> </border> </controltemplate> </itemscontrol.template> <itemscontrol.itemspanel x:uid="pageitemtemplate"> <itemspaneltemplate> <stackpanel orientation="horizontal"/> </itemspaneltemplate> </itemscontrol.itemspanel> <itemscontrol.itemtemplate> <datatemplate> <button x:name="pagenumberbutton" margin="3,4" style="{staticresource buttonstyle}" content="{binding path=page_number}"></button> </datatemplate> </itemscontrol.itemtemplate> </itemscontrol> <button content="next" grid.row="1" height="23" horizontalalignment="left" margin="136,98,0,0" name="nextbutton" verticalalignment="top" width="75" click="button1_click" /> </grid> </window>
mainwindow.xaml.cs
public partial class mainwindow : window,inotifypropertychanged { observablecollection<pagenumber> pagecollection = new observablecollection<pagenumber>(); public mainwindow() { initializecomponent(); pagecollection.add(new pagenumber(" 0 ")); pagecollection.add(new pagenumber(" 1 ")); pagecollection.add(new pagenumber(" 2 ")); pagecollection.add(new pagenumber(" 3 ")); pagecollection.add(new pagenumber(" 4 ")); pagecollection.add(new pagenumber(" 5 ")); this.datacontext = this; } public observablecollection<pagenumber> pagecollection { { return this.pagecollection; } set { this.pagecollection = value; this.onpropertychanged("pagecollection"); } } private int currentpage; public int currentpage { { return currentpage; } set { currentpage = value; this.onpropertychanged("currentpage"); } } private void button1_click(object sender, routedeventargs e) { #region -- if comment code there no problem,,,problem occures when uncomment code,,, -- pagecollection.clear(); pagecollection.add(new pagenumber(" 0 ")); pagecollection.add(new pagenumber(" 1 ")); pagecollection.add(new pagenumber(" 2 ")); #endregion (int = 0; < pagecontrol.items.count; i++) { var container = pagecontrol.itemcontainergenerator.containerfromindex(i) contentpresenter; var button = container.contenttemplate.findname("pagenumberbutton", container) button; if (button.content.equals(string.format(" {0} ", currentpage))) { button.background = brushes.navajowhite; } else { button.background = nextbutton.background; } } currentpage++; } #region -- inotifypropertychanged members -- public event propertychangedeventhandler propertychanged; public void onpropertychanged(string propertynamearg) { propertychangedeventhandler handler = this.propertychanged; if (handler != null) { handler(this,new propertychangedeventargs(propertynamearg)); } } #endregion } public class pagenumber { private string page_number; public pagenumber(string pagenumberarg) { this.page_number = pagenumberarg; } public string page_number { { return page_number; } set { page_number = value; } } }
there's no need of inotifypropertychanged interface on derived object dependencyobject. should use dependencyproperty instead.
it not practice change whole observablecollection, create 1 , don't destroy it: clear instead.
it's wrong practice access items hosted inside itemscontrol (more in general inside visual tree). within button click handler write following:
button btn = (button)e.originalsource; pagenumber pn = (pagenumber)btn.datacontext; this.currentpage = pn.page;
however, must add new property named "page" (type "int") in pagenumber class.
to control button color, i'd use converter multibinding.
public class buttoncolorconverter : imultivalueconverter { public object convert(object[] values, type targettype, object parameter, cultureinfo culture) { int current = (int)values[0]; int button = (int)values[1]; return button == current ? brushes.navajowhite : brushes.xxx; //set desired color } public object[] convertback(object value, type[] targettypes, object parameter, cultureinfo culture) { throw new notimplementedexception(); } }
however, xaml must changed accordingly:
<itemscontrol.itemtemplate> <datatemplate> <button x:name="pagenumberbutton" margin="3,4" style="{staticresource buttonstyle}" content="{binding path=page_number}"> <button.background> <multibinding converter="{staticresource xxx}"> //specify converter seen above <binding path="currentpage" relativesource="{relativesource mode=findancestor, ancestortype={x:type window}}" /> <binding path="page" /> </multibinding> </button.background> </button> </datatemplate> </itemscontrol.itemtemplate>
i didn't test program, should work.
cheers
Comments
Post a Comment