Friday, April 29, 2011

Refactoring method that binds controls to LINQ

I have a function that binds LINQ results to the controls on my form. The below code works but I just can't get over the feeling I should be slapped for the copy/paste aspect. Can someone help me with what i need to do to deodorize this?

Thank You!

private void BindDataToForm()
    {
        // Bind data to form
        CaseNotesDataContext db = new CaseNotesDataContext();
        Table<CN_MaintItem> caseNotesItems = db.GetTable<CN_MaintItem>();

        // For each object
        var contactType = from cType in caseNotesItems
                          where cType.CategoryID == 2
                          select cType.ItemDescription;
        chkContactType.DataSource = contactType;

        var contactLocation = from cLocation in caseNotesItems
                          where cLocation.CategoryID == 3
                          select cLocation.ItemDescription;
        lkuContactLocation.Properties.DataSource = contactLocation;

        var contactMethod = from cMethod in caseNotesItems
                          where cMethod.CategoryID == 4
                          select cMethod.ItemDescription;
        lkuContactMethod.Properties.DataSource = contactMethod;

        var contactWith = from cWith in caseNotesItems
                          where cWith.CategoryID == 5
                          select cWith.ItemDescription;
        chkContactWith.DataSource = contactWith;

        var domains = from d in caseNotesItems
                          where d.CategoryID == 6
                          select d.ItemDescription;
        chkDomains.DataSource = domains;
    }
From stackoverflow
  • You can 'shorten' it by doing something like:

    IQueryable<string> GetDescriptions(int cat)
    {
      return from x in caseNotesItems
             where x.CategoryID == cat
             select x.ItemDescription;
    
    }
    

    And then:

    chkDomains.DataSource = GetDescriptions(6);
    ...
    
    Nick Berardi : You are not passing the table in at all
    leppie : Oh noes, end of the friggen world, fill in that gaps Nick...
    Nick Berardi : Well it makes all the difference, why go through the effort of making actual C# and then call it pseudo code?
    leppie : Instance variables, what a novel idea! I never said it was pseudo code, and don't plan on ever spoon feeding or just giving copy/paste answers. Sorry, if it disturbed you.
  • I don't know if this really solves anything but try:

    public static class MyExtentsions {
        public IQueryable<string> GetItemDescriptions(this Table<CN_MaintItem> table, int cat)
        {
            return from x in table
                   where x.CategoryID == cat
                   select x.ItemDescription;
        }
    }
    

    So you can pull the information like this:

    using (CaseNotesDataContext db = new CaseNotesDataContext()) {
        Table<CN_MaintItem> caseNotesItems = db.GetTable<CN_MaintItem>();
    
        chkContactType.DataSource = caseNotesItems.GetItemDescriptions(2);
        lkuContactLocation.Properties.DataSource = caseNotesItems.GetItemDescriptions(3);
        // etc... 
    }
    
    Refracted Paladin : Thanks, this seems to be on the right track. Mine isn't liking "this" though. "Extension method can only be declared in non-generic,non-nested static class" Ideas??
    Nick Berardi : Yeah you need to declare it in a static class. public static class MyExtensions { (put it here) }
  • The trick is to store the information required to bind the controls explictly. You could create a IDictionary<Control, Int32> to store the category id for each control. Then just iterate over all controls, look up the id in the dictionary, and finally bind it if an entry exists. You can extend this method by creating a dictionary with a delegates as values. This allows you to perform different queries for different controls. Further you could also use the Control.Tag property to store this information.

0 comments:

Post a Comment