Created
July 17, 2013 15:32
-
-
Save HamGuy/6021689 to your computer and use it in GitHub Desktop.
ExtendedListBox
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Text; | |
| using System.Windows; | |
| using System.Windows.Controls; | |
| using System.Windows.Media; | |
| namespace HamGuyToolkit.Controls | |
| { | |
| public class ExtendedListBox : ListBox | |
| { | |
| public event RoutedEventHandler OnScrollToBottom; | |
| private ScrollViewer _scrollViewer = null; | |
| private bool _isHookedScrollEvent = false; | |
| public ExtendedListBox() | |
| { | |
| this.Loaded += ExtendedListBox_Loaded; | |
| this.LayoutUpdated += ExtendedListBox_LayoutUpdated; | |
| } | |
| void ExtendedListBox_LayoutUpdated(object sender, EventArgs e) | |
| { | |
| if (_scrollViewer != null) | |
| return; | |
| _scrollViewer = FindFirstVisualElement<ScrollViewer>(this); | |
| if (_isHookedScrollEvent) | |
| { | |
| return; | |
| } | |
| if (_scrollViewer != null) | |
| { | |
| _isHookedScrollEvent = true; | |
| FrameworkElement element = VisualTreeHelper.GetChild(_scrollViewer, 0) as FrameworkElement; | |
| if (element != null) | |
| { | |
| VisualStateGroup visualStateGroup = FindVisualState(element, "ScrollStates"); | |
| visualStateGroup.CurrentStateChanged += new EventHandler<VisualStateChangedEventArgs>(visualStateGroup_CurrentStateChanged); | |
| } | |
| } | |
| } | |
| void ExtendedListBox_Loaded(object sender, System.Windows.RoutedEventArgs e) | |
| { | |
| if (_scrollViewer != null) | |
| return; | |
| _scrollViewer = FindFirstVisualElement<ScrollViewer>(this); | |
| if (_isHookedScrollEvent) | |
| { | |
| return; | |
| } | |
| if (_scrollViewer != null) | |
| { | |
| _isHookedScrollEvent = true; | |
| FrameworkElement element = VisualTreeHelper.GetChild(_scrollViewer, 0) as FrameworkElement; | |
| if (element != null) | |
| { | |
| VisualStateGroup visualStateGroup = FindVisualState(element, "ScrollStates"); | |
| visualStateGroup.CurrentStateChanged += new EventHandler<VisualStateChangedEventArgs>(visualStateGroup_CurrentStateChanged); | |
| } | |
| } | |
| } | |
| void visualStateGroup_CurrentStateChanged(object sender, VisualStateChangedEventArgs e) | |
| { | |
| var visualState = e.NewState.Name; | |
| if (visualState == "NotScrolling") | |
| { | |
| var v1 = Math.Round(_scrollViewer.ExtentHeight - _scrollViewer.VerticalOffset); | |
| var v2 = Math.Round(_scrollViewer.ViewportHeight); | |
| if (v1 <= v2) | |
| { | |
| // TODO: Load more data action | |
| if (OnScrollToBottom != null) | |
| OnScrollToBottom(this, new RoutedEventArgs()); | |
| } | |
| } | |
| } | |
| private T FindFirstVisualElement<T>(DependencyObject container) where T : DependencyObject | |
| { | |
| var childQueue = new Queue<DependencyObject>(); | |
| childQueue.Enqueue(container); | |
| while (childQueue.Count > 0) | |
| { | |
| var current = childQueue.Dequeue(); | |
| T result = current as T; | |
| if (result != null && result != container) | |
| { | |
| return result; | |
| } | |
| int childCount = VisualTreeHelper.GetChildrenCount(current); | |
| for (int childIndex = 0; childIndex < childCount; childIndex++) | |
| { | |
| childQueue.Enqueue(VisualTreeHelper.GetChild(current, childIndex)); | |
| } | |
| } | |
| return null; | |
| } | |
| private VisualStateGroup FindVisualState(FrameworkElement element, string name) | |
| { | |
| if (element == null) | |
| { | |
| return null; | |
| } | |
| var groups = VisualStateManager.GetVisualStateGroups(element); | |
| foreach (VisualStateGroup group in groups) | |
| { | |
| if (group.Name == name) | |
| { | |
| return group; | |
| } | |
| } | |
| return null; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment