c# - WPF-MVVM, Master - Detail datagrid with calculated column. Rate * Quantity = Total -


i have data entry form bound viewmodel. follow ef code-first approach , details tables represented observable collections in models, below.

public partial class item {      public item()     {         orders = new observablecollection<order>();     } } 

everything works fine in few cases have master entry detail in form of grid. here's xaml part binds selecteditem.orders detail grid.

<usercontrol x:class="abcd.views.itemview"     ....     datacontext="{binding itemmaster, source={staticresource locator}}"     height="auto" width="auto">     <grid>          <grid.columndefinitions.... />         <grid.rowdefinitions..../>         <datagrid autogeneratecolumns="false" verticalalignment="top" itemssource="{binding items}" selecteditem="{binding selecteditem}" name="dgitems" horizontalalignment="stretch" rowdetailsvisibilitymode="visiblewhenselected" >              <datagrid.columns>                         <datagridtextcolumn x:name="itemnamecolumn" binding="{binding path=itemname}" header="item name" width="125" />                         <datagridtextcolumn x:name="itemcodecolumn" binding="{binding path=itemcode}" header="item code" width="75" />                         <datagridtextcolumn x:name="stockcolumn" binding="{binding path=stocklevel}" header="stock" width="60" />              </datagrid.columns>         </datagrid>         <label grid.column="3" grid.row="0" margin="3,3,3,3" content="item code"      verticalalignment="center" />         <textbox grid.column="4" grid.row="0" horizontalalignment="left" margin="3,3,3,3" name="ctrlitemcode" text="{binding path=selecteditem.itemcode, mode=twoway, validatesonexceptions=true, notifyonvalidationerror=true}" width="120" height="auto" verticalcontentalignment="center" />         <label grid.column="3" grid.row="2" margin="3,3,3,3" content="product name" verticalalignment="center" />         <textbox grid.column="4" grid.row="2" horizontalalignment="left" margin="3,3,3,3" name="ctrlproductname" text="{binding path=selecteditem.itemname, mode=twoway, validatesonexceptions=true, notifyonvalidationerror=true}" width="120" height="auto" verticalcontentalignment="center" />         <datagrid grid.column="2" grid.row="16" grid.columnspan="3"  height="145" autogeneratecolumns="false" verticalalignment="top" itemssource="{binding selecteditem.orders}"  name="dgorders" horizontalalignment="stretch" >              <datagrid.columns>                   <datagridtemplatecolumn width="120">                        <datagridtemplatecolumn.celltemplate>                             <datatemplate>                                  <combobox displaymemberpath="ordernumber" selectedvaluepath="orderid"  itemssource="{binding path=datacontext.orders,   relativesource={relativesource findancestor, ancestortype={x:type usercontrol}}}" selectedvalue="{binding path=orderid}" />                              </datatemplate>                         </datagridtemplatecolumn.celltemplate>                   </datagridtemplatecolumn>                   <datagridtextcolumn x:name="qtycolumn" binding="{binding path=quantity}" header="qty" width="75" />                   <datagridtextcolumn x:name="pricecolumn" binding="{binding path=price}" header="price" width="75" />                   <datagridtextcolumn x:name="totalcolumn" binding="{binding path=total}" header="total" width="75" />               </datagrid.columns>         </datagrid>    </grid>  </usercontrol> 

in such cases, want calculate total user types price , quantity in grid. know can handled if have related property in viewmodel. in case, orders collection in item model.

thanks in advance.

ok, after searching , seeking support in forums, found solution suits case. posting here it's useful somebody.

briefing final answer worked me. can done wrap each entity viewmodel. datagrid uses collection there binds it's itermssource observablecollection of ordervm rather order (which of entity type ).

and can wrap properties of entity properties in viewmodel , put business logic in there calculations , raising property changed on calculated field when 1 of it's factors changes.

according suggestion below changes in code helped me issue resolved; ordervm collection below;

 public class ordervm : baseviewmodel {     public ordervm()     {   }     private order _order;     public order order     {                 {             return _order;         }         set         {             _order = value;             notifypropertychanged();         }     } public decimal percentage     {                 {             return (decimal)_order.percentage; //without passing selectedorder.percentage this, doesn't work         }         set         {             _order.percentage = value;             notifypropertychanged();             calculate();         }     }     public decimal qty     {                 {             return (decimal)_order.qty;         }         set         {             _order.qty = value;             notifypropertychanged();             calculate();         }     }     public decimal total     {                 {             return (decimal)_order.total;         }         set         {             _order.total = value;             notifypropertychanged();         }     }     private void calculate()     {         _order.total = _order.price * _order.qty;         notifypropertychanged("total");     }  } 

the itemvm (mainvm) having below 3 important properties, orders = observablecollection of ordervm selecteditem //item selected edit selectedorder //order selected edit

public class itemsvm : baseviewmodel {     private item _selecteditem;     private observablecollection<ordervm> _orders;     public observablecollection<ordervm> orders     {                 {             if (selecteditem != null)             {                 _orders = new observablecollection<ordervm>();                 foreach (order ord in selecteditem.orders)                 {                     _orders.add(new ordervm { order = ord });                 }                 return _orders;             }             else                 return null;         }         set { _orders = value; }     } 

//selecteditem property public item selecteditem { { return _selecteditem; } set { _selecteditem = value; notifypropertychanged(); notifypropertychanged("canmodify"); notifypropertychanged("orders"); } }

private ordervm _selectedorder;     public ordervm selectedorder     {                 {             return _selectedorder;         }         set         {             _selectedorder = value;             notifypropertychanged();         }     } } 

and xaml below;

<datagrid grid.column="2" grid.row="16" grid.columnspan="3"  height="145" autogeneratecolumns="false" verticalalignment="top"        itemssource="{binding orders}" selecteditem="{binding selectedorder}" name="dgorders" horizontalalignment="stretch" >     <datagrid.columns>         <datagridtextcolumn x:name="qtycolumn" binding="{binding path=qty}" header="qty" width="75" />         <datagridtextcolumn x:name="pricecolumn" binding="{binding path=price}" header="price" width="75" />         <datagridtextcolumn x:name="totalcolumn" binding="{binding path=total}" header="price" width="75" />     </datagrid.columns> </datagrid> 

the total conversation can found @ conversation @ msdn forums


Comments