JD2022-TU1/main/tools/framework/JD.WPF/Controls/ListBoxExtensions.cs

103 lines
3.7 KiB
C#

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<ListBox, AutoScrollInfo> m_activeControls = new Dictionary<ListBox, AutoScrollInfo>();
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]);
}
}
}
}
}