How to bind a datagrid row with text boxes in wpf mvvm -
i have datagrid contains product details , need load product details textboxes when double click on particular product in datagrid.
thanks in advance.
welcome stackoverflow! people won't answer questions without following.
- a clear summary of you're attempting do.
- all of relevant code
- any exceptions experiencing
- all of research links used in order are
that said, give demo of you're asking for.
here xaml
<window x:class="datagriddemo.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:viewmodel="clr-namespace:datagriddemo" title="mainwindow" height="350" width="420" background="gray"> <!--this define resource xaml here going use. can see, importing our view model--> <window.resources> <viewmodel:productgridviewmodel x:key="productviewmodel"/> </window.resources> <!--this main layout of xaml. in grid below, set "datacontext" our static resource defined above. tell inside grid, "if don't define own data context, you're going use mine" because of this, of elements inside grid have access public properties of viewmodel--> <grid datacontext="{staticresource resourcekey=productviewmodel}"> <grid.columndefinitions> <columndefinition width="300"/> <columndefinition width="100"/> </grid.columndefinitions> <!-- datagrid displaying. 2 important things note here "itemssource" , "selecteditem". "itemssource" collection want display in our grid. product models stored. selectedproduct going selected grid row stored can access data text boxes defined below. --> <datagrid width="500" grid.column="0" autogeneratecolumns="false" itemssource="{binding products}" selecteditem="{binding selectedproduct, mode=twoway}"> <datagrid.columns> <datagridtextcolumn isreadonly="true" header="product id" binding="{binding productid, updatesourcetrigger=propertychanged}" /> <datagridtextcolumn isreadonly="true" header="product name" binding="{binding productname, updatesourcetrigger=propertychanged}" /> <datagridtextcolumn isreadonly="true" header="total sold" binding="{binding totalsold, updatesourcetrigger=propertychanged}" /> </datagrid.columns> </datagrid> <!-- stack panel contains text boxes going use edit our data. notice bindings point selectedproduct.property. because accessing properties inside of selectedproduct property in our viewmodel. when edit these text boxes data in grid automatically change. --> <stackpanel height="100" background="wheat" margin="10" orientation="vertical" grid.column="1"> <textblock fontweight="bold" width="100" textwrapping="wrap">update product info!</textblock> <textbox width="100" text="{binding selectedproduct.productname, mode=twoway, updatesourcetrigger=propertychanged}" /> <textbox width="100" text="{binding selectedproduct.totalsold, mode=twoway, updatesourcetrigger=propertychanged}" /> </stackpanel> </grid> </window>
next our viewmodel. if view frosting on cake can think of view model cake around pudding. view model logic lives. sorting, crunching , other stuff.
using system; using system.collections.generic; using system.collections.objectmodel; using system.linq; using system.text; using system.threading.tasks; namespace datagriddemo { public class productgridviewmodel { private productmodel _selectedproduct; private observablecollection<productmodel> _products; /// <summary> /// notice though updates grid /// add or remove elements, doesn't call onproperty /// changed in setter... magic? nope, observable /// collections call onpropertychanged you. /// /// caveat: not call on property changed /// if products = new observablecollection... /// when products.add(yourproduct)... /// </summary> public observablecollection<productmodel> products { { return _products; } set { _products = value; } } /// <summary> /// selected row in grid. automatically changes /// when select new rows because set grid selecteditem property /// mode=twoway /// </summary> public productmodel selectedproduct { { return _selectedproduct; } set { _selectedproduct = value; } } /// <summary> /// view models constructor. get's called automatically when view /// initialized because declared static resource in xaml. /// </summary> public productgridviewmodel() { //dont forget new observable collections!! products = new observablecollection<productmodel>(); //don't forget generate data! generateproducts(); } /// <summary> /// use method generate dummy data /// </summary> private void generateproducts() { (int x = 0; x < 100; x++) { this.products.add(new productmodel(x,"product #"+x,x+50)); } } } }
finally there model. actual data. this, yes this, pudding.
using system; using system.collections.generic; using system.componentmodel; using system.linq; using system.text; using system.threading.tasks; namespace datagriddemo { public class productmodel : inotifypropertychanged { private int32 _productid; private string _productname; private int32 _totalsold; /// <summary> /// note properties below: /// notice first, property names match bound in xaml /// part of grand scheme. /// /// when onproperty changed called, ui knows go search /// properties. it's important these have correct spelling /// , casing. /// </summary> public int32 totalsold { { return _totalsold; } set { _totalsold = value; onpropertychanged("totalsold"); } } public string productname { { return _productname; } set { _productname = value; onpropertychanged("productname"); } } public int32 productid { { return _productid; } set { _productid = value; onpropertychanged("productid"); } } /// <summary> /// normal constructor load our properties. /// </summary> /// <param name="productid"></param> /// <param name="productname"></param> /// <param name="totalsold"></param> public productmodel(int32 productid, string productname, int32 totalsold) { this.productid = productid; this.productname = productname; this.totalsold = totalsold; } /// <summary> /// updating ui /// </summary> public event propertychangedeventhandler propertychanged; /// <summary> /// when property changes in object, if want reflected on /// ui need call function /// </summary> /// <param name="propertyname"></param> public void onpropertychanged(string propertyname) { propertychangedeventhandler handler = propertychanged; if (handler != null) { this.propertychanged(this, new propertychangedeventargs(propertyname)); } } } }
finally here expected result
in first image see our grid loaded new data
if click on row see it's data populate 2 text boxes on side.
finally if change data in text boxes see update in grid immediately.
and that's it! complete mvvm datagrid text box , solution. hope helps. please remember said expected question asker , have fun! welcome wpf , mvvm.
Comments
Post a Comment