c# - How to set a WPF Binding from code to a member of a list that might not yet exist -


allow me first introduce classes using:

public class assessment {     public list<normdefinition> definitions {get;set;}     public list<parameter> parameters {get;set;} }  public class normdefinition {     public string columnname {get;set;} }  public class parameter {     public string name {get;set;}     public list<normvalue> norms {get;set;} }  public class normvalue {     public normdefinition definition {get;set;}     public string value {get;set;} } 

the user navigating through sort of wizard , has complete tasks create assessment.

the first step defining 1 or more normdefinitions. has more settings shown above others irrelevant problem.

the second step define 1 or more parameters. however, user can add values defined normdefinitions. trying creating datagrid itemssource = {binding assessment.parameters}, know source each binding parameter object bound row.

when second screen gets focus, code adds column each normdefinition user might fill in value. creation of columns looks this:

private void createnormdefinitioncolumns() {     foreach (var definition in assessment.definitions)     {         datagridtextcolumn column = new datagridtextcolumn();         column.header = definition.columnname;         column.binding = new binding()         {             // add binding to:             // parameter.norms.single(norm => norm.definition == definition).value;         }         parameterdatagrid.columns.add(column);     } } 

please me solution set binding.

to take 1 step further, in case .single() not return result, normvalue object created , added parameter.

for such case use genericrow , generictable classes:

    public class genericrow : customtypedescriptor, inotifypropertychanged     {          #region private fields         list<propertydescriptor> _property_list = new list<propertydescriptor>();         #endregion          #region inotifypropertychange implementation          public event propertychangedeventhandler propertychanged = delegate { };         protected void onpropertychanged(string propertyname)         {             propertychanged(this, new propertychangedeventargs(propertyname));         }          #endregion inotifypropertychange implementation          #region public methods          public void setpropertyvalue<t>(string propertyname, t propertyvalue)         {             var properties = this.getproperties()                                     .cast<propertydescriptor>()                                     .where(prop => prop.name.equals(propertyname));              if (properties == null || properties.count() != 1)             {                 throw new exception("the property doesn't exist.");             }              var property = properties.first();             property.setvalue(this, propertyvalue);              onpropertychanged(propertyname);         }          public t getpropertyvalue<t>(string propertyname)         {             var properties = this.getproperties()                                 .cast<propertydescriptor>()                                 .where(prop => prop.name.equals(propertyname));              if (properties == null || properties.count() != 1)             {                 throw new exception("the property doesn't exist.");             }              var property = properties.first();             return (t)property.getvalue(this);         }          public void addproperty<t, u>(string propertyname) u : genericrow         {             var customproperty =                     new custompropertydescriptor<t>(                                             propertyname,                                             typeof(u));              _property_list.add(customproperty);         }          #endregion          #region overriden methods          public override propertydescriptorcollection getproperties()         {             var properties = base.getproperties();             return new propertydescriptorcollection(                                 properties.cast<propertydescriptor>()                                           .concat(_property_list).toarray());         }          #endregion           } 

and:

 public class generictable {      private string tablename = "";     public string tablename     {         { return tablename; }         set { tablename = value; }     }      private observablecollection<datagridcolumn> columncollection;     public observablecollection<datagridcolumn> columncollection     {         { return columncollection; }         private set { columncollection = value; }     }      private observablecollection<genericrow> genericrowcollection;     public observablecollection<genericrow> genericrowcollection     {         { return genericrowcollection; }         set { genericrowcollection = value; }     }         public generictable(string tablename)     {         this.tablename = tablename;         columncollection = new observablecollection<datagridcolumn>();         genericrowcollection = new observablecollection<genericrow>();      }      /// <summary>     /// columnname binding property name     /// </summary>     /// <param name="columnname"></param>     public void addcolumn(string columnname)     {         datagridtextcolumn column = new datagridtextcolumn();         column.header = columnname;         column.binding = new binding(columnname);         columncollection.add(column);     }        public override string tostring()     {         return tablename;      }   } 

Comments