Implementing IEnumerable<T> and DataBinding to a GridView

Discussion in 'C#' started by jimrthy, Apr 16, 2007.

  1. #1
    This might not be the best forum to ask this, but what the heck. It's not like I hang out on any programmer forums any more.

    This is the first time I've had a chance to play with generics, and I've been beating my head against the wall all day over this. I haven't had any luck with google, the disassembly looks to me like it should be doing what I want, and I'm pretty much just ready to throw my hands up in disgust and sleep on it. But I figured I'd ask first.

    I have a class that implements IEnumerable<T>. I'm trying to use it as an ObjectDataSource.

    I'm not trying to do anything fancy in this class. It just holds the root of a tree.

    One version I'm trying looks like this:

     IEnumerator<IHierarchicalDataRow<String, Int32>> IEnumerable<IHierarchicalDataRow<String, Int32>>.GetEnumerator()
        {
            throw new Exception("Just to prove that I never get here");
        }
    
        //public IEnumerator<IHierarchicalDataRow<String, Int32>> GetEnumerator()
        public IEnumerator GetEnumerator()
        {
            throw new Exception( "Just to prove that I never get here" );
            foreach( IHierarchicalDataRow<String, Int32> row in root )
            {
                yield return row;
            }
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new Exception("To prove that I was never here, either");
        }
    
    Code (markup):
    I've tried various combinations of EIMI. If I leave the non-generic interface version implicit, then it actually does get called. But it will not call either other version (I obviously had to change the name of the method that's actually trying to do something when I went this route). It does something (because it does take time to return), but I can't tell what. (I'm about ready to break down and install WinDbg, and I really thought I'd put that sort of experience behind me for good).

    No matter what I've tried, I wind up in the GridView's OnRowDataBound with a null data item.

    Does this ring any bells with anyone? Suggestions about what to google?

    I have a minimalist version of this same setup in a console app, except it just does a for loop to 10. So I'm pretty sure I'm on the right track (aside from the fact that pretty much every example I've found on line looks very similar to this). I tried just using a similar for loop here, with the same results.

    Thanks in advance,
    James
     
    jimrthy, Apr 16, 2007 IP
  2. ccoonen

    ccoonen Well-Known Member

    Messages:
    1,606
    Likes Received:
    71
    Best Answers:
    0
    Trophy Points:
    160
    #2
    I'm not a C# developer but I have implemnted iEnumerable in my shopping cart class so I can enumerate over CartItem objs. maybe try to take a step back. are you loading the data twice and not letting viewstate control it? (as in fill the data only if not postback)?
     
    ccoonen, Apr 17, 2007 IP
  3. jimrthy

    jimrthy Guest

    Messages:
    283
    Likes Received:
    13
    Best Answers:
    0
    Trophy Points:
    0
    #3
    Actually, in this context, I don't want ViewState to control it. I want ControlState to remember the actual state of certain elements of the control, but not the data in the grid. It's a big, nasty control that does all sorts of crazy stuff which is just silly. Because that's what the customer wants.

    Anyway, for the sake of posterity, here's the actual answer. (Who knows, maybe this will turn up on google the next time someone types in ObjectDataSource HOWTO):

    When you're wiring up the ObjectDataSource via the GUI, it lets you first select a class that has members with a particular signature. Then it lets you pick one of those members. One of the methods it looks for is the IEnumerable interface: something that returns an IEnumerator.

    I was wiring my collection class' enumeration method as SELECT. So my ObjectDataSource's SELECT method looked like:

    public IEnumerator<T> GetEnumerable()
    {
    	// ...do some stuff
    	yield return nextRow;
    }
    Code (markup):
    The problem is that that's exactly not what ObjectDataSource is looking for. It really wants you to return something else that implements IEnumerable. The method you set up as SELECT is just supposed to hydrate your actual recordset (i.e. pull it out of persistent storage, or wherever, and set it up to be enumerated through in the code-behind).

    So, realistically, I need another class layer that initializes my collection and then returns it.

    The quick and dirty fix was to add a method to my collection class:
    
    public IEnumerable<T> GetRecordSet()
    {
    	return this;
    }
    Code (markup):
    Set that up as my SELECT method, and the problem went away.

    Thanks to everyone who's read this, and especially to ccoonen for offering up that suggestion.
     
    jimrthy, Apr 21, 2007 IP