1 using System;
2 using System.Collections.Generic;
3 using System.Collections.ObjectModel;
4 using System.ComponentModel;
5 using System.Diagnostics;
6 using System.Linq;
7 using System.Windows;
8 using System.Windows.Controls;
9 using System.Windows.Controls.Primitives;
10 using System.Windows.Input;
11 using System.Windows.Media;
12
13 namespace TreeViewDemo
14 {
15 /// <summary>
16 /// 支持虚拟化的wrappanel
17 /// </summary>
18 public class VirtualizingWrapPanel : VirtualizingPanel, IScrollInfo
19 {
20 #region Fields
21
22 UIElementCollection _children;
23 ItemsControl _itemsControl;
24 IItemContainerGenerator _generator;
25 private Point _offset = new Point(0, 0);
26 private Size _extent = new Size(0, 0);
27 private Size _viewport = new Size(0, 0);
28 private int firstIndex = 0;
29 private Size childSize;
30 private Size _pixelMeasuredViewport = new Size(0, 0);
31 Dictionary<UIElement, Rect> _realizedChildLayout = new Dictionary<UIElement, Rect>();
32 WrapPanelAbstraction _abstractPanel;
33
34
35 #endregion
36
37 #region Properties
38
39 private Size ChildSlotSize
40 {
41 get
42 {
43 return new Size(ItemWidth, ItemHeight);
44 }
45 }
46
47 #endregion
48
49 #region Dependency Properties
50
51 [TypeConverter(typeof(LengthConverter))]
52 public double ItemHeight
53 {
54 get
55 {
56 return (double)base.GetValue(ItemHeightProperty);
57 }
58 set
59 {
60 base.SetValue(ItemHeightProperty, value);
61 }
62 }
63
64 [TypeConverter(typeof(LengthConverter))]
65 public double ItemWidth
66 {
67 get
68 {
69 return (double)base.GetValue(ItemWidthProperty);
70 }
71 set
72 {
73 base.SetValue(ItemWidthProperty, value);
74 }
75 }
76
77 public Orientation Orientation
78 {
79 get { return (Orientation)GetValue(OrientationProperty); }
80 set { SetValue(OrientationProperty, value); }
81 }
82
83 public static readonly DependencyProperty ItemHeightProperty = DependencyProperty.Register("ItemHeight", typeof(double), typeof(VirtualizingWrapPanel), new FrameworkPropertyMetadata(double.PositiveInfinity));
84 public static readonly DependencyProperty ItemWidthProperty = DependencyProperty.Register("ItemWidth", typeof(double), typeof(VirtualizingWrapPanel), new FrameworkPropertyMetadata(double.PositiveInfinity));
85 public static readonly DependencyProperty OrientationProperty = StackPanel.OrientationProperty.AddOwner(typeof(VirtualizingWrapPanel), new FrameworkPropertyMetadata(Orientation.Horizontal));
86
87 #endregion
88
89 #region Methods
90
91 public void SetFirstRowViewItemIndex(int index)
92 {
93 SetVerticalOffset((index) / Math.Floor((_viewport.Width) / childSize.Width));
94 SetHorizontalOffset((index) / Math.Floor((_viewport.Height) / childSize.Height));
95 }
96
97 private void Resizing(object sender, EventArgs e)
98 {
99 if (_viewport.Width != 0)
100 {
101 int firstIndexCache = firstIndex;
102 _abstractPanel = null;
103 MeasureOverride(_viewport);
104 SetFirstRowViewItemIndex(firstIndex);
105 firstIndex = firstIndexCache;
106 }
107 }
108
109 public int GetFirstVisibleSection()
110 {
111 int section;
112 var maxSection = _abstractPanel.Max(x => x.Section);
113 if (Orientation == Orientation.Horizontal)
114 {
115 section = (int)_offset.Y;
116 }
117 else
118 {
119 section = (int)_offset.X;
120 }
121 if (section > maxSection)
122 section = maxSection;
123 return section;
124 }
125
126 public int GetFirstVisibleIndex()
127 {
128 int section = GetFirstVisibleSection();
129 var item = _abstractPanel.Where(x => x.Section == section).FirstOrDefault();
130 if (item != null)
131 return item._index;
132 return 0;
133 }
134
135 private void CleanUpItems(int minDesiredGenerated, int maxDesiredGenerated)
136 {
137 for (int i = _children.Count - 1; i >= 0; i--)
138 {
139 GeneratorPosition childGeneratorPos = new GeneratorPosition(i, 0);
140 int itemIndex = _generator.IndexFromGeneratorPosition(childGeneratorPos);
141 if (itemIndex < minDesiredGenerated || itemIndex > maxDesiredGenerated)
142 {
143 _generator.Remove(childGeneratorPos, 1);
144 RemoveInternalChildRange(i, 1);
145 }
146 }
147 }
148
149 private void ComputeExtentAndViewport(Size pixelMeasuredViewportSize, int visibleSections)
150 {
151 if (Orientation == Orientation.Horizontal)
152 {
153 _viewport.Height = visibleSections;
154 _viewport.Width = pixelMeasuredViewportSize.Width;
155 }
156 else
157 {
158 _viewport.Width = visibleSections;
159 _viewport.Height = pixelMeasuredViewportSize.Height;
160 }
161
162 if (Orientation == Orientation.Horizontal)
163 {
164 _extent.Height = _abstractPanel.SectionCount + ViewportHeight - 1;
165
166 }
167 else
168 {
169 _extent.Width = _abstractPanel.SectionCount + ViewportWidth - 1;
170 }
171 _owner.InvalidateScrollInfo();
172 }
173
174 private void ResetScrollInfo()
175 {
176 _offset.X = 0;
177 _offset.Y = 0;
178 }
179
180 private int GetNextSectionClosestIndex(int itemIndex)
181 {
182 var abstractItem = _abstractPanel[itemIndex];
183 if (abstractItem.Section < _abstractPanel.SectionCount - 1)
184 {
185 var ret = _abstractPanel.
186 Where(x => x.Section == abstractItem.Section + 1).
187 OrderBy(x => Math.Abs(x.SectionIndex - abstractItem.SectionIndex)).
188 First();
189 return ret._index;
190 }
191 else
192 return itemIndex;
193 }
194
195 private int GetLastSectionClosestIndex(int itemIndex)
196 {
197 var abstractItem = _abstractPanel[itemIndex];
198 if (abstractItem.Section > 0)
199 {
200 var ret = _abstractPanel.
201 Where(x => x.Section == abstractItem.Section - 1).
202 OrderBy(x => Math.Abs(x.SectionIndex - abstractItem.SectionIndex)).
203 First();
204 return ret._index;
205 }
206 else
207 return itemIndex;
208 }
209
210 private void NavigateDown()
211 {
212 var gen = _generator.GetItemContainerGeneratorForPanel(this);
213 UIElement selected = (UIElement)Keyboard.FocusedElement;
214 int itemIndex = gen.IndexFromContainer(selected);
215 int depth = 0;
216 while (itemIndex == -1)
217 {
218 selected = (UIElement)VisualTreeHelper.GetParent(selected);
219 itemIndex = gen.IndexFromContainer(selected);
220 depth++;
221 }
222 DependencyObject next = null;
223 if (Orientation == Orientation.Horizontal)
224 {
225 int nextIndex = GetNextSectionClosestIndex(itemIndex);
226 next = gen.ContainerFromIndex(nextIndex);
227 while (next == null)
228 {
229 SetVerticalOffset(VerticalOffset + 1);
230 UpdateLayout();
231 next = gen.ContainerFromIndex(nextIndex);
232 }
233 }
234 else
235 {
236 if (itemIndex == _abstractPanel._itemCount - 1)
237 return;
238 next = gen.ContainerFromIndex(itemIndex + 1);
239 while (next == null)
240 {
241 SetHorizontalOffset(HorizontalOffset + 1);
242 UpdateLayout();
243 next = gen.ContainerFromIndex(itemIndex + 1);
244 }
245 }
246 while (depth != 0)
247 {
248 next = VisualTreeHelper.GetChild(next, 0);
249 depth--;
250 }
251 (next as UIElement).Focus();
252 }
253
254 private void NavigateLeft()
255 {
256 var gen = _generator.GetItemContainerGeneratorForPanel(this);
257
258 UIElement selected = (UIElement)Keyboard.FocusedElement;
259 int itemIndex = gen.IndexFromContainer(selected);
260 int depth = 0;
261 while (itemIndex == -1)
262 {
263 selected = (UIElement)VisualTreeHelper.GetParent(selected);
264 itemIndex = gen.IndexFromContainer(selected);
265 depth++;
266 }
267 DependencyObject next = null;
268 if (Orientation == Orientation.Vertical)
269 {
270 int nextIndex = GetLastSectionClosestIndex(itemIndex);
271 next = gen.ContainerFromIndex(nextIndex);
272 while (next == null)
273 {
274 SetHorizontalOffset(HorizontalOffset - 1);
275 UpdateLayout();
276 next = gen.ContainerFromIndex(nextIndex);
277 }
278 }
279 else
280 {
281 if (itemIndex == 0)
282 return;
283 next = gen.ContainerFromIndex(itemIndex - 1);
284 while (next == null)
285 {
286 SetVerticalOffset(VerticalOffset - 1);
287 UpdateLayout();
288 next = gen.ContainerFromIndex(itemIndex - 1);
289 }
290 }
291 while (depth != 0)
292 {
293 next = VisualTreeHelper.GetChild(next, 0);
294 depth--;
295 }
296 (next as UIElement).Focus();
297 }
298
299 private void NavigateRight()
300 {
301 var gen = _generator.GetItemContainerGeneratorForPanel(this);
302 UIElement selected = (UIElement)Keyboard.FocusedElement;
303 int itemIndex = gen.IndexFromContainer(selected);
304 int depth = 0;
305 while (itemIndex == -1)
306 {
307 selected = (UIElement)VisualTreeHelper.GetParent(selected);
308 itemIndex = gen.IndexFromContainer(selected);
309 depth++;
310 }
311 DependencyObject next = null;
312 if (Orientation == Orientation.Vertical)
313 {
314 int nextIndex = GetNextSectionClosestIndex(itemIndex);
315 next = gen.ContainerFromIndex(nextIndex);
316 while (next == null)
317 {
318 SetHorizontalOffset(HorizontalOffset + 1);
319 UpdateLayout();
320 next = gen.ContainerFromIndex(nextIndex);
321 }
322 }
323 else
324 {
325 if (itemIndex == _abstractPanel._itemCount - 1)
326 return;
327 next = gen.ContainerFromIndex(itemIndex + 1);
328 while (next == null)
329 {
330 SetVerticalOffset(VerticalOffset + 1);
331 UpdateLayout();
332 next = gen.ContainerFromIndex(itemIndex + 1);
333 }
334 }
335 while (depth != 0)
336 {
337 next = VisualTreeHelper.GetChild(next, 0);
338 depth--;
339 }
340 (next as UIElement).Focus();
341 }
342
343 private void NavigateUp()
344 {
345 var gen = _generator.GetItemContainerGeneratorForPanel(this);
346 UIElement selected = (UIElement)Keyboard.FocusedElement;
347 int itemIndex = gen.IndexFromContainer(selected);
348 int depth = 0;
349 while (itemIndex == -1)
350 {
351 selected = (UIElement)VisualTreeHelper.GetParent(selected);
352 itemIndex = gen.IndexFromContainer(selected);
353 depth++;
354 }
355 DependencyObject next = null;
356 if (Orientation == Orientation.Horizontal)
357 {
358 int nextIndex = GetLastSectionClosestIndex(itemIndex);
359 next = gen.ContainerFromIndex(nextIndex);
360 while (next == null)
361 {
362 SetVerticalOffset(VerticalOffset - 1);
363 UpdateLayout();
364 next = gen.ContainerFromIndex(nextIndex);
365 }
366 }
367 else
368 {
369 if (itemIndex == 0)
370 return;
371 next = gen.ContainerFromIndex(itemIndex - 1);
372 while (next == null)
373 {
374 SetHorizontalOffset(HorizontalOffset - 1);
375 UpdateLayout();
376 next = gen.ContainerFromIndex(itemIndex - 1);
377 }
378 }
379 while (depth != 0)
380 {
381 next = VisualTreeHelper.GetChild(next, 0);
382 depth--;
383 }
384 (next as UIElement).Focus();
385 }
386
387
388 #endregion
389
390 #region Override
391
392 protected override void OnKeyDown(KeyEventArgs e)
393 {
394 switch (e.Key)
395 {
396 case Key.Down:
397 NavigateDown();
398 e.Handled = true;
399 break;
400 case Key.Left:
401 NavigateLeft();
402 e.Handled = true;
403 break;
404 case Key.Right:
405 NavigateRight();
406 e.Handled = true;
407 break;
408 case Key.Up:
409 NavigateUp();
410 e.Handled = true;
411 break;
412 default:
413 base.OnKeyDown(e);
414 break;
415 }
416 }
417
418
419 protected override void OnItemsChanged(object sender, ItemsChangedEventArgs args)
420 {
421 base.OnItemsChanged(sender, args);
422 _abstractPanel = null;
423 ResetScrollInfo();
424 }
425
426 protected override void OnInitialized(EventArgs e)
427 {
428 this.SizeChanged += new SizeChangedEventHandler(this.Resizing);
429 base.OnInitialized(e);
430 _itemsControl = ItemsControl.GetItemsOwner(this);
431 _children = InternalChildren;
432 _generator = ItemContainerGenerator;
433 }
434
435 protected override Size MeasureOverride(Size availableSize)
436 {
437 if (_itemsControl == null || _itemsControl.Items.Count == 0)
438 return availableSize;
439 if (_abstractPanel == null)
440 _abstractPanel = new WrapPanelAbstraction(_itemsControl.Items.Count);
441
442 _pixelMeasuredViewport = availableSize;
443
444 _realizedChildLayout.Clear();
445
446 Size realizedFrameSize = availableSize;
447
448 int itemCount = _itemsControl.Items.Count;
449 int firstVisibleIndex = GetFirstVisibleIndex();
450
451 GeneratorPosition startPos = _generator.GeneratorPositionFromIndex(firstVisibleIndex);
452
453 int childIndex = (startPos.Offset == 0) ? startPos.Index : startPos.Index + 1;
454 int current = firstVisibleIndex;
455 int visibleSections = 1;
456 using (_generator.StartAt(startPos, GeneratorDirection.Forward, true))
457 {
458 bool stop = false;
459 bool isHorizontal = Orientation == Orientation.Horizontal;
460 double currentX = 0;
461 double currentY = 0;
462 double maxItemSize = 0;
463 int currentSection = GetFirstVisibleSection();
464 while (current < itemCount)
465 {
466 bool newlyRealized;
467
468 // Get or create the child
469 UIElement child = _generator.GenerateNext(out newlyRealized) as UIElement;
470 if (newlyRealized)
471 {
472 // Figure out if we need to insert the child at the end or somewhere in the middle
473 if (childIndex >= _children.Count)
474 {
475 base.AddInternalChild(child);
476 }
477 else
478 {
479 base.InsertInternalChild(childIndex, child);
480 }
481 _generator.PrepareItemContainer(child);
482 child.Measure(ChildSlotSize);
483 }
484 else
485 {
486 // The child has already been created, let's be sure it's in the right spot
487 Debug.Assert(child == _children[childIndex], "Wrong child was generated");
488 }
489 childSize = child.DesiredSize;
490 Rect childRect = new Rect(new Point(currentX, currentY), childSize);
491 if (isHorizontal)
492 {
493 maxItemSize = Math.Max(maxItemSize, childRect.Height);
494 if (childRect.Right > realizedFrameSize.Width) //wrap to a new line
495 {
496 currentY = currentY + maxItemSize;
497 currentX = 0;
498 maxItemSize = childRect.Height;
499 childRect.X = currentX;
500 childRect.Y = currentY;
501 currentSection++;
502 visibleSections++;
503 }
504 if (currentY > realizedFrameSize.Height)
505 stop = true;
506 currentX = childRect.Right;
507 }
508 else
509 {
510 maxItemSize = Math.Max(maxItemSize, childRect.Width);
511 if (childRect.Bottom > realizedFrameSize.Height) //wrap to a new column
512 {
513 currentX = currentX + maxItemSize;
514 currentY = 0;
515 maxItemSize = childRect.Width;
516 childRect.X = currentX;
517 childRect.Y = currentY;
518 currentSection++;
519 visibleSections++;
520 }
521 if (currentX > realizedFrameSize.Width)
522 stop = true;
523 currentY = childRect.Bottom;
524 }
525 _realizedChildLayout.Add(child, childRect);
526 _abstractPanel.SetItemSection(current, currentSection);
527
528 if (stop)
529 break;
530 current++;
531 childIndex++;
532 }
533 }
534 CleanUpItems(firstVisibleIndex, current - 1);
535
536 ComputeExtentAndViewport(availableSize, visibleSections);
537
538 return availableSize;
539 }
540 protected override Size ArrangeOverride(Size finalSize)
541 {
542 if (_children != null)
543 {
544 foreach (UIElement child in _children)
545 {
546 var layoutInfo = _realizedChildLayout[child];
547 child.Arrange(layoutInfo);
548 }
549 }
550 return finalSize;
551 }
552
553 #endregion
554
555 #region IScrollInfo Members
556
557 private bool _canHScroll = false;
558 public bool CanHorizontallyScroll
559 {
560 get { return _canHScroll; }
561 set { _canHScroll = value; }
562 }
563
564 private bool _canVScroll = false;
565 public bool CanVerticallyScroll
566 {
567 get { return _canVScroll; }
568 set { _canVScroll = value; }
569 }
570
571 public double ExtentHeight
572 {
573 get { return _extent.Height; }
574 }
575
576 public double ExtentWidth
577 {
578 get { return _extent.Width; }
579 }
580
581 public double HorizontalOffset
582 {
583 get { return _offset.X; }
584 }
585
586 public double VerticalOffset
587 {
588 get { return _offset.Y; }
589 }
590
591 public void LineDown()
592 {
593 if (Orientation == Orientation.Vertical)
594 SetVerticalOffset(VerticalOffset + 20);
595 else
596 SetVerticalOffset(VerticalOffset + 1);
597 }
598
599 public void LineLeft()
600 {
601 if (Orientation == Orientation.Horizontal)
602 SetHorizontalOffset(HorizontalOffset - 20);
603 else
604 SetHorizontalOffset(HorizontalOffset - 1);
605 }
606
607 public void LineRight()
608 {
609 if (Orientation == Orientation.Horizontal)
610 SetHorizontalOffset(HorizontalOffset + 20);
611 else
612 SetHorizontalOffset(HorizontalOffset + 1);
613 }
614
615 public void LineUp()
616 {
617 if (Orientation == Orientation.Vertical)
618 SetVerticalOffset(VerticalOffset - 20);
619 else
620 SetVerticalOffset(VerticalOffset - 1);
621 }
622
623 public Rect MakeVisible(Visual visual, Rect rectangle)
624 {
625 var gen = (ItemContainerGenerator)_generator.GetItemContainerGeneratorForPanel(this);
626 var element = (UIElement)visual;
627 int itemIndex = gen.IndexFromContainer(element);
628 while (itemIndex == -1)
629 {
630 element = (UIElement)VisualTreeHelper.GetParent(element);
631 itemIndex = gen.IndexFromContainer(element);
632 }
633 int section = _abstractPanel[itemIndex].Section;
634 Rect elementRect = _realizedChildLayout[element];
635 if (Orientation == Orientation.Horizontal)
636 {
637 double viewportHeight = _pixelMeasuredViewport.Height;
638 if (elementRect.Bottom > viewportHeight)
639 _offset.Y += 1;
640 else if (elementRect.Top < 0)
641 _offset.Y -= 1;
642 }
643 else
644 {
645 double viewportWidth = _pixelMeasuredViewport.Width;
646 if (elementRect.Right > viewportWidth)
647 _offset.X += 1;
648 else if (elementRect.Left < 0)
649 _offset.X -= 1;
650 }
651 InvalidateMeasure();
652 return elementRect;
653 }
654
655 public void MouseWheelDown()
656 {
657 PageDown();
658 }
659
660 public void MouseWheelLeft()
661 {
662 PageLeft();
663 }
664
665 public void MouseWheelRight()
666 {
667 PageRight();
668 }
669
670 public void MouseWheelUp()
671 {
672 PageUp();
673 }
674
675 public void PageDown()
676 {
677 SetVerticalOffset(VerticalOffset + _viewport.Height * 0.8);
678 }
679
680 public void PageLeft()
681 {
682 SetHorizontalOffset(HorizontalOffset - _viewport.Width * 0.8);
683 }
684
685 public void PageRight()
686 {
687 SetHorizontalOffset(HorizontalOffset + _viewport.Width * 0.8);
688 }
689
690 public void PageUp()
691 {
692 SetVerticalOffset(VerticalOffset - _viewport.Height * 0.8);
693 }
694
695 private ScrollViewer _owner;
696 public ScrollViewer ScrollOwner
697 {
698 get { return _owner; }
699 set { _owner = value; }
700 }
701
702 public void SetHorizontalOffset(double offset)
703 {
704 if (offset < 0 || _viewport.Width >= _extent.Width)
705 {
706 offset = 0;
707 }
708 else
709 {
710 if (offset + _viewport.Width >= _extent.Width)
711 {
712 offset = _extent.Width - _viewport.Width;
713 }
714 }
715
716 _offset.X = offset;
717
718 if (_owner != null)
719 _owner.InvalidateScrollInfo();
720
721 InvalidateMeasure();
722 firstIndex = GetFirstVisibleIndex();
723 }
724
725 public void SetVerticalOffset(double offset)
726 {
727 if (offset < 0 || _viewport.Height >= _extent.Height)
728 {
729 offset = 0;
730 }
731 else
732 {
733 if (offset + _viewport.Height >= _extent.Height)
734 {
735 offset = _extent.Height - _viewport.Height;
736 }
737 }
738
739 _offset.Y = offset;
740
741 if (_owner != null)
742 _owner.InvalidateScrollInfo();
743
744 //_trans.Y = -offset;
745
746 InvalidateMeasure();
747 firstIndex = GetFirstVisibleIndex();
748 }
749
750 public double ViewportHeight
751 {
752 get { return _viewport.Height; }
753 }
754
755 public double ViewportWidth
756 {
757 get { return _viewport.Width; }
758 }
759
760 #endregion
761
762 #region helper data structures
763
764 class ItemAbstraction
765 {
766 public ItemAbstraction(WrapPanelAbstraction panel, int index)
767 {
768 _panel = panel;
769 _index = index;
770 }
771
772 WrapPanelAbstraction _panel;
773
774 public readonly int _index;
775
776 int _sectionIndex = -1;
777 public int SectionIndex
778 {
779 get
780 {
781 if (_sectionIndex == -1)
782 {
783 return _index % _panel._averageItemsPerSection - 1;
784 }
785 return _sectionIndex;
786 }
787 set
788 {
789 if (_sectionIndex == -1)
790 _sectionIndex = value;
791 }
792 }
793
794 int _section = -1;
795 public int Section
796 {
797 get
798 {
799 if (_section == -1)
800 {
801 return _index / _panel._averageItemsPerSection;
802 }
803 return _section;
804 }
805 set
806 {
807 if (_section == -1)
808 _section = value;
809 }
810 }
811 }
812
813 class WrapPanelAbstraction : IEnumerable<ItemAbstraction>
814 {
815 public WrapPanelAbstraction(int itemCount)
816 {
817 List<ItemAbstraction> items = new List<ItemAbstraction>(itemCount);
818 for (int i = 0; i < itemCount; i++)
819 {
820 ItemAbstraction item = new ItemAbstraction(this, i);
821 items.Add(item);
822 }
823
824 Items = new ReadOnlyCollection<ItemAbstraction>(items);
825 _averageItemsPerSection = itemCount;
826 _itemCount = itemCount;
827 }
828
829 public readonly int _itemCount;
830 public int _averageItemsPerSection;
831 private int _currentSetSection = -1;
832 private int _currentSetItemIndex = -1;
833 private int _itemsInCurrentSecction = 0;
834 private object _syncRoot = new object();
835
836 public int SectionCount
837 {
838 get
839 {
840 int ret = _currentSetSection + 1;
841 if (_currentSetItemIndex + 1 < Items.Count)
842 {
843 int itemsLeft = Items.Count - _currentSetItemIndex;
844 ret += itemsLeft / _averageItemsPerSection + 1;
845 }
846 return ret;
847 }
848 }
849
850 private ReadOnlyCollection<ItemAbstraction> Items { get; set; }
851
852 public void SetItemSection(int index, int section)
853 {
854 lock (_syncRoot)
855 {
856 if (section <= _currentSetSection + 1 && index == _currentSetItemIndex + 1)
857 {
858 _currentSetItemIndex++;
859 Items[index].Section = section;
860 if (section == _currentSetSection + 1)
861 {
862 _currentSetSection = section;
863 if (section > 0)
864 {
865 _averageItemsPerSection = (index) / (section);
866 }
867 _itemsInCurrentSecction = 1;
868 }
869 else
870 _itemsInCurrentSecction++;
871 Items[index].SectionIndex = _itemsInCurrentSecction - 1;
872 }
873 }
874 }
875
876 public ItemAbstraction this[int index]
877 {
878 get { return Items[index]; }
879 }
880
881 #region IEnumerable<ItemAbstraction> Members
882
883 public IEnumerator<ItemAbstraction> GetEnumerator()
884 {
885 return Items.GetEnumerator();
886 }
887
888 #endregion
889
890 #region IEnumerable Members
891
892 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
893 {
894 return GetEnumerator();
895 }
896
897 #endregion
898 }
899
900 #endregion
901 }
902 }