I am replacing my home grown 'Transposed UltraGrid w/header section on a data repeater' with a 'Card Spaced UltraGrid w/header section on a data repeater'. I am very close but there is an 'annoying' behavior I can't seem to find addressed in the IG model. Anyways, here is the symptom. I have given the users the ability to scroll the individual Card Spaced (single row) grids horizontally. So the user scrolls the grid on one Data Repeater item over to the records for October then decide to look at October on a different Data Repeater 'row' and as soon as they click in that data repeater 'row' the grid on the previous 'row' resets back to January.
Can I stop this from happening?
I seem to remember that there were a couple properties of the WinGrid that were specific to the VB Data Repeater control (I spotted them when the app was being developed a couple years ago and have since 'lost them'). Perhaps they are something I need to look at. Can you point me to where I saw those, too?
Thanks in advance.
Hi,
I'm afraid I don't understand your description of the issue. Could you post a small sample project or maybe some screen shots so I can see what you mean?
Mitchster2 said:I seem to remember that there were a couple properties of the WinGrid that were specific to the VB Data Repeater control
There are no such properties that I am aware of. The grid has no knowledge of, nor connection to, the DataRepeater - at least not directly.
Well, I knew I saw something about a DataRepeater in there...
InitializeDataRepeaterClone (Inherited from Infragistics.Win.UltraControlBase)
and I read about some problems people had with 'mismatching' but honestly ... it took some work to understand the DataRepeater. It uses an item template and then clones the templates to create the items but then it sometimes re-uses them and ... well, it is a little raggedy around the edges. One secret that took some experimenting to get correct is that many (but not all) controls require that their native events (like UltraGrid's InitializeLayout and AfterCellUpdate event) need to be wired up with an AddEvent Handler riff in the repeater's ItemCloned event.
That said we have an enterprise app up and running that uses this control exensively.
Each Data Repeater item (think of it as a panel) has two columns. The first is a header identifying a particular piece. The second column has an UltraGrid which lists all the instances when that piece is needed (by date). Up until about a week ago that was a transposed grid where I was doing all the footwork to make the grid behave like an Ultra Grid in Card Space mode. Each time a Data Repeater item performs it's DrawItem event I LINQ filter my child datatable and bind.
Everything was cool, but we had upgraded the IG package and I decided to give the Card Space feature another go. It is working swimmingly.
The original implementation had some cool code that allowed me to scroll the whole details section (across all Data Repeaters at once) with some arrow keys. It even had some code to only scroll as far as need to get the last set so the user would never be stuck with like one record on the last details screen they scroll to.
Now that I am using the Card Space I have set each Data Repeater item to all have their own horizontal scrollbars for their own grid.
So my user is looking at part A and scrolls the grid on part A's Ultra grid over to show some of the records not currently visible.
Then they decide to look at Part B in the repeater panel just below Part A's.
As sonn as they change the focus away from Part A's panel, the UltraGrid zooms back to it's original position at the first record.
In my original home grown method they could flip through those details like a book but I would be satisfied to just be able to give them the ability to scroll the details grids individually but those individual grids on the repeaters need to persist their scrolled positon when they lose focus.
It would be a big pain to send a sample project ... I guess I could do a wash out against a screenshot... but I am hoping I have explained well enough.
Thanks, Mike.
I looked for InitializeDataRepeaterClone and it looks like this was added to UltraControlBase (not specifically to the grid, but basically for all Infragistics Winforms controls) to fix a bug having to do with the cloning of event handlers by the DataRepeater. So it doesn't seem like that has any bearing here.
I'm still not sure I completely understand the situation. I think part of the problem is some of the terminology you are using. When you say "Card Space" are you talking about CardView? If not, then I don't know what "Card Space" is.
So if that's what you meant then let me see if I have this straight. On a DataRepeater, you have a grid in CardView mode. The grid, I assume, is showing more than one row (card). So the user can scroll the cards. But if the user scrolls the card area and then switches focus away from the grid an onto a different record in the repeater, then it loses the scroll position. Is that right?
If so, then the question is - what is either your code or the DataRepeater doing that causes the grid to scroll. This is pretty tough to guess at because I'm still not sure exactly what is scrolling.
It could be that the grid is getting re-bound to the same data source or a new data source and thus it's losing it's layout and state information such as scroll position. But that doesn't make a lot of sense, since the same thing would have happened whether you are in CardView or not.
Another possibility is that the BindingManager is positioning to the first row and the grid is activating that row and scrolling it into view. Again, CardView wouldn't make any difference here, so I don't see why it would suddenly start happening, now. But you could try setting grid.SyncWithCurrencyManager to false to prevent the grid from synchronizing it's position with the BindingManager and see if that helps.
If none of that helps, then you might want to put a breakpoint in the grid's various Scroll events like AfterRowRegionScroll and AfterColRegionScroll and look at the call stack to see why the grid is scrolling in this particular case.
Well, the fix doesn't always work ... several IG controls require that their various events be explicitly set in the repeater's ItemCloned event.
Yes, terminology is always an issue. For example a Data Repeater doesn't have rows, it has Items which are clones of it's Template. Yes, I meant Card Space, but before we get too far on that ... the issue occurs when the grid is set to Card Space or not. I get the same behavior. And by a single row I meant MaxCardAreaRows = 1.
The reason it didn't happen before was because I had built into my 'transposing code' for the grid a paging paradigm that allowed me to scroll all of the grids at once (the implementation is closely tied to the Data Repeater's DrawItem event which is an 'oddball' event that can be thought of as a Paint wherein the form goes through the Repeater's clones (and there are as many as there are Repeater items on screen although the repeater control re-uses them). Then there is a mechanism for creating alternate versions of the templates and ... on and on. The Draw Item event goes off all the time ... Hmmm. So, theoretically, if I could test the Item to see if it was last used for the same part I am currently 'Drawing'; I could gather the scroll position... and reset it after the draw... maybe.
So, just to be sure, you are saying that if i put two ultra grids on a form and they have enough records to require scrolling that if i scroll one and then move to the other one then I should not expect the first one to automatically scroll back to the first record? In other words, i must be re-setting the binding (somewhere) to be getting this behavior, right?
It is the last thing I wanted to get done before I push this to QA, I know I will get some negative feedback on this but I don't have several days ...
Well, if you want some advice... create an IG Data Repeater that isn't a raggedy MS/POS one. It is just a specialized Grid whose cells are control containers.
No charge for the advice...
That would rock.
If you send me an email direct with an email to send it to I will send you a screen shot but I can't just post one.
Mitchster2 said:the issue occurs when the grid is set to Card Space or not. I get the same behavior.
Okay, that makes sense. I couldn't think of any reason why CardView should make any difference here, so it's good to know it doesn't. :)
Mitchster2 said:So, just to be sure, you are saying that if i put two ultra grids on a form and they have enough records to require scrolling that if i scroll one and then move to the other one then I should not expect the first one to automatically scroll back to the first record?
Typically you should not. The only time that this would happen is if both grid are on the same container (i.e. both directly on the form, as opposed to each being inside another container like panel on that form) and they are both bound to the same data source. The BindingManager uses the containing control to get tge BindingContext. So any two bound controls within the same container and bound to the same data source will synchronize to the same current row. I don't think that's the case here, since each grid is in it's own container (the DataRepeater). I supposed it's conceivable that the DataRepeater deliberately uses the same BindingContext for every item. If that is the case, then you could work around this by simply setting the grid.BindingContext to a new BindingContext so that each grid's context is different.
Mitchster2 said:Well, if you want some advice... create an IG Data Repeater that isn't a raggedy MS/POS one. It is just a specialized Grid whose cells are control containers.
You can Submit a Feature Request for this. :)
Okay, with your help, I identified the issue. Duh. The grid located on the DataRepeater Item is dynamically bound to a LINQ filtered Datatable and the only real way I can see to do that is in the DataRepeater's DrawItem event ... and that DrawItem event goes off 'all the time'. I created a quick version that just bound to a Dataset that had the relation set between the two Datatables so that I could avoid rebinding but it was a performance dog. I also searched through the DataRepeater's model (again) but it is missing several events that would help (Before and After events in particular)
So, it looks like I am going to have to go back to my original custom 'paging' of all of the datagrids and remove the individual scrolling. Interesting.
Last thing though, I was curious if you could provide a small sample of how I would properly implement the :
InitializeDataRepeaterClone()
InitializeDataRepeaterClones()
methods for my grids, which are one of the controls which reside on the DataRepeater ItemTemplate clones in my solution.
I currently use something like the following in the DataRepeater.ItemCloned event:
But if you guys already have this covered I would probably be better off using your solution... i have enough wheel prototypes laying around already.
Thanks.
I think all you have to do it... every time the DataRepeater created a new template, you have to call InitializeDataRepeaterClones and pass in the original template and the new one. This will loop through all of the controls in the template and clone the event handlers properly. You could also just call InitializeDataRepeaterClone on each UltraControl on the template directly, if you don't want to loop.