@pduncan 和 @MattBurland 的答案都有一些问题,主要是他们未能正确取消注册行为。
此实现将处理程序存储在另一个附加属性中,以便您可以通过绑定来打开和关闭行为。
请注意,这适用于ListView. 如果您正在使用ListBox,请将出现的ListViewto更改为ListBox。
public static class ListViewExtensions
{
public static readonly DependencyProperty AutoScrollToEndProperty = DependencyProperty.RegisterAttached("AutoScrollToEnd", typeof(bool), typeof(ListViewExtensions), new UIPropertyMetadata(OnAutoScrollToEndChanged));
private static readonly DependencyProperty AutoScrollToEndHandlerProperty = DependencyProperty.RegisterAttached("AutoScrollToEndHandler", typeof(NotifyCollectionChangedEventHandler), typeof(ListViewExtensions));
public static bool GetAutoScrollToEnd(DependencyObject obj) => (bool)obj.GetValue(AutoScrollToEndProperty);
public static void SetAutoScrollToEnd(DependencyObject obj, bool value) => obj.SetValue(AutoScrollToEndProperty, value);
private static void OnAutoScrollToEndChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
{
var listView = s as ListView;
if (listView == null)
return;
var source = (INotifyCollectionChanged)listView.Items.SourceCollection;
if ((bool)e.NewValue)
{
NotifyCollectionChangedEventHandler scrollToEndHandler = delegate
{
if (listView.Items.Count <= 0)
return;
listView.Items.MoveCurrentToLast();
listView.ScrollIntoView(listView.Items.CurrentItem);
};
source.CollectionChanged += scrollToEndHandler;
listView.SetValue(AutoScrollToEndHandlerProperty, scrollToEndHandler);
}
else
{
var handler = (NotifyCollectionChangedEventHandler)listView.GetValue(AutoScrollToEndHandlerProperty);
source.CollectionChanged -= handler;
}
}
}
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
<ListView local:ListViewExtensions.AutoScrollToEnd="{Binding Path=AutoScroll}">
Run Code Online (Sandbox Code Playgroud)
我还将它设置为静态类,因为您不需要实例化它(也不需要从 派生DependencyObject)。转换为INotifyCollectionChanged已更改,以便错误作为转换异常而不是 NRE 出现。