c# - Can you bind a complex type in a DataGridComboBoxColumn in a DataGrid in WPF? -


so 1 curious on may have change code base if cannot data right. hoping binding expert on wpf has had similar , knew how it. following guide, http://wpfthoughts.blogspot.com/2015/04/cannot-find-governing-frameworkelement.html, binding value in list shown in datagrid combobox. works great, if property in collection of objects primitive type. if complex not much. want update property when changes implementing inotifypropertychanged.

feel free download source code easier reference: https://github.com/djangojazz/comboboxindatagridviewwpf

baseviewmodel(just inotifypropertychanged reuse):

public abstract class baseviewmodel : inotifypropertychanged {     public event propertychangedeventhandler propertychanged;      public void onpropertychanged(string propertyname)     {       propertychangedeventhandler handler = this.propertychanged;       if (handler != null)       {         var e = new propertychangedeventargs(propertyname);         handler(this, e);       }     } } 

essentially have models such:

public class type {     public type(int typeid, string typename)     {       typeid = typeid;       typename = typename;     }      public int typeid { get; set; }     public string typename { get; set; } }   public class transactionsimple : baseviewmodel {     public transactionsimple(int transactionid, string description, int typeid, decimal amount)     {       transactionid = transactionid;       description = description;       typeid = typeid;       amount = amount;     }      public int transactionid { get; set; }     public string description { get; set; }     private int _typeid;      public int typeid     {       { return _typeid; }       set       {         _typeid = value;         onpropertychanged(nameof(typeid));       }     }      public decimal amount { get; set; } }  public class transactioncomplex : baseviewmodel {     public transactioncomplex(int transactionid, string description, int typeid, string typename, decimal amount)     {       transactionid = transactionid;       description = description;       type = new type(typeid, typename);       amount = amount;     }      public int transactionid { get; set; }     public string description { get; set; }     private type _type;      public type type     {       { return _type; }       set       {         if(_type != null) { messagebox.show($"change {value.typename}"); }         _type = value;         onpropertychanged(nameof(type));       }     }      public decimal amount { get; set; } } 

and viewmodel:

public sealed class mainwindowviewmodel : baseviewmodel {     private observablecollection<transactionsimple> _simples;     private observablecollection<transactioncomplex> _complexes;       public mainwindowviewmodel()     {       fakerepo();     }      private readonlycollection<type> _types;      public readonlycollection<type> types     {       => (_types != null) ? _types : _types = new readonlycollection<type>(new list<type> { new type(1, "credit"), new type(2, "debit") });     }       public observablecollection<transactionsimple> simples     {       { return _simples; }       set       {         _simples = value;         onpropertychanged(nameof(simples));       }     }     public observablecollection<transactioncomplex> complexes     {       { return _complexes; }       set       {         _complexes = value;         onpropertychanged(nameof(complexes));       }     }      private void fakerepo()     {       var data = new list<transactioncomplex>       {         new transactioncomplex(1, "got money", 1, "credit", 1000m),         new transactioncomplex(2, "spent money", 2, "debit", 100m),         new transactioncomplex(3, "spent more money", 2, "debit", 300m)       };        complexes = new observablecollection<transactioncomplex>(data);       simples = new observablecollection<transactionsimple>(data.select(x => new transactionsimple(x.transactionid, x.description, x.type.typeid, x.amount)));     } } 

updated 2:24 pm pst usa: , view(almost working):

<window x:class="comboboxindatagridviewwpf.mainwindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:comboboxindatagridviewwpf"         mc:ignorable="d"         title="mainwindow" height="350" width="525">   <window.resources>     <collectionviewsource x:key="types" source="{binding types}"/>   </window.resources>     <grid>     <grid.rowdefinitions>       <rowdefinition height="auto"/>       <rowdefinition height="*"/>       <rowdefinition height="auto"/>       <rowdefinition height="auto"/>       <rowdefinition height="*"/>     </grid.rowdefinitions>     <label content="simpleexample" />     <datagrid grid.row="1" itemssource="{binding simples}" autogeneratecolumns="false">       <datagrid.columns>         <datagridtextcolumn header="transactionid" binding="{binding transactionid}" />         <datagridtextcolumn header="description" binding="{binding description}" />         <datagridcomboboxcolumn header="type" itemssource="{binding source={staticresource types}}" displaymemberpath="typename" selectedvaluepath="typeid" selectedvaluebinding="{binding path=typeid}" />         <datagridtextcolumn header="amount" binding="{binding amount}" />       </datagrid.columns>     </datagrid>     <border grid.row="2" height="50" background="black" />     <label content="complexobjectexample" grid.row="3" />     <datagrid grid.row="4" itemssource="{binding complexes}" autogeneratecolumns="false">       <datagrid.columns>         <datagridtextcolumn header="transactionid" binding="{binding transactionid}" />         <datagridtextcolumn header="description" binding="{binding description}" />          <!--this 1 works displays not updates         <datagridtemplatecolumn header="type">           <datagridtemplatecolumn.celleditingtemplate>             <datatemplate>               <combobox itemssource="{binding source={staticresource types}}" displaymemberpath="typename"  selecteditem="{binding type, mode=twoway}" selectedvalue="{binding type.typeid}" />             </datatemplate>           </datagridtemplatecolumn.celleditingtemplate>           <datagridtemplatecolumn.celltemplate>             <datatemplate>               <textblock text="{binding type.typename}"/>             </datatemplate>           </datagridtemplatecolumn.celltemplate>         </datagridtemplatecolumn>-->          <!--this 1 works initial displays wrong. seems closest want-->         <datagridcomboboxcolumn header="type" selecteditembinding="{binding type}"  >           <datagridcomboboxcolumn.elementstyle>             <style targettype="combobox">               <setter property="itemssource" value="{binding relativesource={relativesource findancestor, ancestortype={x:type window}}, path=datacontext.types}"/>               <setter property="displaymemberpath" value="typename" />               <setter property="selecteditem" value="{binding type}" />               <setter property="isreadonly" value="true"/>             </style>           </datagridcomboboxcolumn.elementstyle>           <datagridcomboboxcolumn.editingelementstyle>             <style targettype="combobox">               <setter property="itemssource" value="{binding relativesource={relativesource findancestor, ancestortype={x:type window}}, path=datacontext.types}"/>               <setter property="displaymemberpath" value="typename" />               <setter property="selecteditem" value="{binding type}" />             </style>           </datagridcomboboxcolumn.editingelementstyle>         </datagridcomboboxcolumn>          <!--this 1 not work @         <datagridtemplatecolumn header="type">           <datagridtemplatecolumn.celltemplate>             <datatemplate>               <combobox itemssource="{binding path=datacontext.types,                                             relativesource={relativesource mode=findancestor, ancestortype=window}}"                       displaymemberpath="typename" selecteditem="{binding type}"/>             </datatemplate>           </datagridtemplatecolumn.celltemplate>         </datagridtemplatecolumn>-->         <datagridtextcolumn header="amount" binding="{binding amount}" />       </datagrid.columns>     </datagrid>   </grid> </window> 

the problem shown this: enter image description here

i can items bound combobox , have seen adding observable collections(not shown) , raising properties complex type getting called. not display no matter try. trying property of property type.typename or such different combinations doesn't work. ideas?

this ridiculous behaviour known. because datagridcolumn lies not in visual tree, classic way using datagridcomboboxcolumn bind items parent tried not working.

instead create datagridtemplatecolumn combobox inside. should solve problem in same way. if want bind typeid code works:

<datagridtemplatecolumn header="type">     <datagridtemplatecolumn.celltemplate>         <datatemplate>             <combobox itemssource="{binding path=datacontext.types,                                             relativesource={relativesource mode=findancestor, ancestortype=window}}"                       displaymemberpath="typename"                       selectedvaluepath="typeid"                       selectedvalue="{binding path=typeid, updatesourcetrigger=propertychanged}"/>         </datatemplate>     </datagridtemplatecolumn.celltemplate> </datagridtemplatecolumn> 

binding whole type done changing combobox to:

<combobox itemssource="{binding path=datacontext.types,                                 relativesource={relativesource mode=findancestor, ancestortype=window}}"           displaymemberpath="typename"           selecteditem="{binding path=type, updatesourcetrigger=propertychanged}"/> 

alternatively can have at question other possible solutions described.


Comments

Popular posts from this blog

What is happening when Matlab is starting a "parallel pool"? -

angular - DownloadURL return null in below code -

php - Cannot override Laravel Spark authentication with own implementation -