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 }