Using reflection to assign control value property a data column name...

Last post 07-07-2009 11:55 PM by drpcken. 4 replies.

Sort Posts:

  • Using reflection to assign control value property a data column name...

    07-03-2009, 12:21 PM
    • Member
      454 point Member
    • drpcken
    • Member since 12-15-2005, 12:45 PM
    • Jackson, TN
    • Posts 342

     I have a pretty large webform that spans about 4 ajax TabPanel tabs.   Normally I just write the code to populate each control with the proper value I pull using LINQ to SQL.  But in my quest to learn more about c# I wondered if I could loop through all the controls in the form and populate them abstractly without having to say Control.Text = linqobject.field etc...

    I was discussing this with a friend of mine who said he uses reflection to accomplish this.  Granted ne never writes asp.net apps, mostly classes and libraries in VB.NET.  To start off I named my controls with the corresponding column name from the database, for example my column name from the db is 'FirstName', so I would name my corresponding textbox 'txtFirstName'.  I think this will make it easier to give relation to the control and its field in the db. 

    So I started studying reflection and understand WHAT it does (exposes an object's types, methods, etc..), just not how it does it.  I started playing with it for about 3 hours last night and literally got no where.  My friend really tried to help but he's never worked with asp.net or c# before and was lost also.  What he recommended is returning the record from linq into a collection or list, and then looping through all the controls in my form and setting the value property to the corresponding column name.  I'm pulling my data in using the following LINQ query:

    var contact = (from company in db.Contacts
                           from plan in
                               (
                                   from p in db.PlanOptionsForContacts
                                   where p.ContactID == company.ContactID
                                   select p
                               ).DefaultIfEmpty()
                           from dental in
                               (
                                from d in db.DentalPlansForContacts
                                where d.ContactID == company.ContactID
                                select d
                               ).DefaultIfEmpty()
                           where company.ContactID == cid
                           select new {company, plan, dental}).Single();


    Now I HAVE to use the .Single() method to fill my company, plan, and dental objects because I'm still using controls that manually get filled by them.  Like so:

    txtCompanyName.Text = contact.company.CompanyName;


    But when I use the .Single() method, it makes my contact object not IEnuermable anymore (right??), therefore I can't GetType().GetField() each contact object to return the fieldname.  At this point I'm at a lost.  I can vision what I want to do but have no idea how to get there. Something like:

    foreach (Control c in Controls)
            {
    
                if (c.GetType() == typeof(TextBox))
                {
                    c.Text = contact.dental.? //FieldName generated from c.ID
    
                    
                }
            }

    How can I accomplish this?  Sorry if the question is vague, I'm exhausted :)  Thank you!


  • Re: Using reflection to assign control value property a data column name...

    07-06-2009, 2:40 AM
    • Participant
      856 point Participant
    • Revdoniv
    • Member since 06-29-2009, 6:58 AM
    • Posts 168

    foreach (Control c in Page.Controls)
                {
                    if (c.GetType() == typeof(System.Web.UI.HtmlControls.HtmlForm))
                    {
                        foreach (Control formControl in c.Controls)
                        {
                            Type controlType = formControl.GetType();
                            if (controlType == typeof(TextBox))
                            {
                                //This time get Text Property
                                PropertyInfo info = controlType.GetProperty("Text");

                                //formControl would be your textbox ,
                                //set the text property value as"My dynamic value" or say  your contact.dental.? FieldName generated from c.ID

                                info.SetValue(formControl, "My Own Dynamic Value", null);
                            }

                        }
                    }
                }

    Highlighted part is what you want remaining code is for just understanding.

    See System.Reflection API .

    Dont get confused in Reflection. just check this API ,it has good descriptive documentation so you will not find difficulties in using that.

    Have a Great Day!


    Regards

    Revdoniv

    Please mark this as "Answer" if it helps you
  • Re: Using reflection to assign control value property a data column name...

    07-06-2009, 2:57 PM
    • Member
      454 point Member
    • drpcken
    • Member since 12-15-2005, 12:45 PM
    • Jackson, TN
    • Posts 342

    Thanks Rev!  I was able to figure most of this out myself the last few days.  What I was able to do is loop through my controls, get the ID, and find the corresponding field in the datacontext like so:

    foreach (object innerCtrl in c.Controls)
                                {
                                    if (innerCtrl is TextBox)
                                    {
                                        TextBox txt = (TextBox)innerCtrl;
    
                                        var fld = (from v in contact.vision.GetType().GetProperties()
                                                   where v.Name == txt.ID.Remove(0, 3).ToString()
                                                   select v).DefaultIfEmpty().Single();
    
                                        if (fld != null)
                                        {
                                            txt.Text = Convert.ToString(fld.GetValue(contact.vision, null));
                                        }
                                        else
                                        {
                                            Response.Write(String.Format("<font style='color'red;'>Problem with field {0}</font><br />", txt.ID.ToString()));
                                        }
                                       
    
                                    }
    }



    This works great to fill my controls in my form.  Now I'm trying to update and insert using LINQ and my datacontext.  I'm able to loop through all the properties of my DataContext object, but I'mhaving a problem with the SetValue method.

    foreach (PropertyInfo field in contact.dental.GetType().GetProperties())  //contact.dental is my DataContext object
                    {
                        
                        if (field.Name.ToString() == "id" || field.Name.ToString() == "ContactID")
                        {
                            continue;
                        }
                        else
                        {
                            Type columnType = field.PropertyType.GetGenericArguments()[0];
                            if (columnType == typeof(DateTime))
                            {
                                RadDatePicker rdp = (RadDatePicker)Globals.FindControlRecursive(ContactTabContainer, string.Format("txt{0}", field.Name.ToString()));
                                    
                                field.SetValue(field, rdp.SelectedDate, null);
                            }
                            //From here I want to set all the DataContext fields then do a db.SubmitChanges
                            
                        }
                        
                    }


    It tells me the object does not match target type

    Any ideas?

  • Re: Using reflection to assign control value property a data column name...

    07-07-2009, 1:16 AM
    • Member
      454 point Member
    • drpcken
    • Member since 12-15-2005, 12:45 PM
    • Jackson, TN
    • Posts 342

    Ok I think I just about got it using this code, but when I'm trying to get the type of the datacontext property (string, datetime, int32, etc...) it returns 'System.Runtime'.

    DentalPlansForContact dp = new DentalPlansForContact();
                    Type dbType = dp.GetType();
    
                    foreach (PropertyInfo field in dbType.GetProperties())
                    {
    
                        if (field.Name.ToString() == "id" || field.Name.ToString() == "ContactID")
                        {
                            continue;
                        }
                        else
                        {
                            Type columnType = field.Name.GetType(); //Trying to get TYPE here!
                            if (columnType == typeof(DateTime))
                            {
    
                                RadDatePicker rdp = (RadDatePicker)Globals.FindControlRecursive(ContactTabContainer, string.Format("txt{0}", field.Name.ToString()));
    
                                field.SetValue(dp, rdp.SelectedDate, null);
                                continue;
    
                            }
                            if (columnType == typeof(String))
                            {
                                TextBox txt = (TextBox)Globals.FindControlRecursive(ContactTabContainer, string.Format("txt{0}", field.Name.ToString()));
    
                                field.SetValue(dp, txt.Text, null);
                                continue;
                            }
                            if (columnType == typeof(Decimal))
                            {
                                TextBox txt = (TextBox)Globals.FindControlRecursive(ContactTabContainer, string.Format("txt{0}", field.Name.ToString()));
    
                                field.SetValue(dp, txt.Text, null);
                                continue;
                            }
                            if (columnType == typeof(Int32))
                            {
                                DropDownList ddl = (DropDownList)Globals.FindControlRecursive(ContactTabContainer, string.Format("ddl{0}", field.Name.ToString()));
    
                                field.SetValue(dp, Convert.ToInt32(ddl.SelectedValue), null);
                                continue;
                            }
    
                        }
    
    
    
                    }
                    db.SubmitChanges();





    DentalPlansForContact dp = new DentalPlansForContact();
                    Type dbType = dp.GetType();

                    foreach (PropertyInfo field in dbType.GetProperties())
                    {

                        if (field.Name.ToString() == "id" || field.Name.ToString() == "ContactID")
                        {
                            continue;
                        }
                        else
                        {
                            Type columnType = field.Name.GetType(); //Trying to get TYPE here!
                            if (columnType == typeof(DateTime))
                            {

                                RadDatePicker rdp = (RadDatePicker)Globals.Fin
    dControlRecursive(ContactTabContainer, string.Format("txt{0}", field.Name.ToString()));

                                field.SetValue(dp, rdp.SelectedDate, null);
                                continue;

                            }
                            if (columnType == typeof(String))
                            {
                                TextBox txt = (TextBox)Globals.FindControlRecursive(ContactTabContainer, string.Format("txt{0}", field.Name.ToString()));

                                field.SetValue(dp, txt.Text, null);
                                continue;
                            }
                            if (columnType == typeof(Decimal))
                            {
                                TextBox txt = (TextBox)Globals.FindControlRecursive(ContactTabContainer, string.Format("txt{0}", field.Name.ToString()));

                                field.SetValue(dp, txt.Text, null);
                                continue;
                            }
                            if (columnType == typeof(Int32))
                            {
                                DropDownList ddl = (DropDownList)Globals.FindControlRecursive(ContactTabContainer, string.Format("ddl{0}", field.Name.ToString()));

                                field.SetValue(dp, Convert.ToInt32(ddl.SelectedValue), null);
                                continue;
                            }

                        }



                    }
                    db.SubmitChanges();
  • Re: Using reflection to assign control value property a data column name...

    07-07-2009, 11:55 PM
    • Member
      454 point Member
    • drpcken
    • Member since 12-15-2005, 12:45 PM
    • Jackson, TN
    • Posts 342

    ok so what I found is I can return the type if it is nullable by using:

    System.Nullable.GetUnderlyingType(field.PropertyType).FullName

    This returns "System.DateTime" or whatever else it could be.  But if my field is not nullable then what do I do?   I must be missing something because it has to be easier than this.

Page 1 of 1 (5 items)