using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Windows; using System.Windows.Controls; using JD.Core; namespace JD.WPF.Controls { public static class ListBoxExtensions { private static readonly Dictionary m_activeControls = new Dictionary(); public static readonly DependencyProperty ScrollOnNewItemProperty = DependencyProperty.RegisterAttached("ScrollOnNewItem", typeof(bool), typeof(ListBoxExtensions), new UIPropertyMetadata(false, OnScrollOnNewItemChanged)); public static bool GetScrollOnNewItem(DependencyObject obj) { return (bool)obj.GetValue(ScrollOnNewItemProperty); } public static void SetScrollOnNewItem(DependencyObject obj, bool value) { obj.SetValue(ScrollOnNewItemProperty, value); } private static void OnScrollOnNewItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ListBox listBox = d as ListBox; if (listBox == null) return; bool oldValue = (bool)e.OldValue, newValue = (bool)e.NewValue; if (newValue == oldValue) return; if (newValue) { if (listBox.IsLoaded) OnListBoxLoaded(listBox, new RoutedEventArgs()); else listBox.Loaded += new RoutedEventHandler(OnListBoxLoaded); listBox.Unloaded += new RoutedEventHandler(OnListBoxUnloaded); } else { OnListBoxUnloaded(listBox, new RoutedEventArgs()); } } private static void OnListBoxLoaded(object sender, RoutedEventArgs e) { ListBox listBox = (ListBox)sender; INotifyCollectionChanged notifyableCollection = listBox.ItemsSource as INotifyCollectionChanged; if (notifyableCollection == null) { CodeHelper.DebugBreak("Trying to activate scroll on added item feature whereas the collection behind does not implement INotifyCollectionChanged. "); return; } listBox.Loaded -= OnListBoxLoaded; m_activeControls[listBox] = new AutoScrollInfo(listBox); } private static void OnListBoxUnloaded(object sender, RoutedEventArgs e) { ListBox listBox = (ListBox)sender; if (m_activeControls.ContainsKey(listBox)) { m_activeControls[listBox].Dispose(); m_activeControls.Remove(listBox); } listBox.Unloaded -= OnListBoxUnloaded; } private class AutoScrollInfo : IDisposable { public readonly ListBox m_listBox; public readonly INotifyCollectionChanged m_notifyableCollection; public AutoScrollInfo(ListBox listBox) { m_listBox = listBox; m_notifyableCollection = listBox.ItemsSource as INotifyCollectionChanged; if (m_notifyableCollection != null) { m_notifyableCollection.CollectionChanged += OnCollectionChanged; } } public void Dispose() { if (m_notifyableCollection != null) { m_notifyableCollection.CollectionChanged -= OnCollectionChanged; } } private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action == NotifyCollectionChangedAction.Add) { m_listBox.ScrollIntoView(e.NewItems[0]); } } } } }