Skip to content

Instantly share code, notes, and snippets.

@HamGuy
Created July 17, 2013 15:32
Show Gist options
  • Select an option

  • Save HamGuy/6021689 to your computer and use it in GitHub Desktop.

Select an option

Save HamGuy/6021689 to your computer and use it in GitHub Desktop.
ExtendedListBox
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