WPF - 在ItemsSource更改时重置ListBox滚动位置
我目前有一个ListBox,其ItemsSource集合绑定到我的viewmodel上IEnumerable类型的属性。当preoprty的引用发生变化时,ListBox会按照预期进行更新,但是如果我有大量的项目集合并滚动到ListBox的底部,然后将引用更改为另一个包含比如1个项目的集合,ListBox视图是空白的并且不显示滚动条。我必须用鼠标滚轮向上滚动列表框,直到看到1个项目。WPF - 在ItemsSource更改时重置ListBox滚动位置
所以,我想我之后,是一种重置ListBox的滚动位置到顶部的方法,每当ItemsSource属性发生变化时,无论该集合有多大或多小,总是显示某些内容。 (改变ItemsSource
的时候对我来说,ListBox
滚动到最后一项最新系列中)
if (listBox.Items.Count > 0) {
listBox.ScrollIntoView(listBox.Items[0]);
}
我无法重现您的问题:
试试这个。无论如何,要将ListBox
滚动到顶端,每次更改ItemsSource
时,都可以使用一些代码。先听在ItemsSourceProperty
更改,然后滚动ListBox
顶端一旦其项目已经产生
更新
做出了附加的行为,这是否来避免后面的代码。它可以像这样使用
<ListBox ...
behaviors:ScrollToTopBehavior.ScrollToTop="True"/>
ScrollToTopBehavior
public static class ScrollToTopBehavior
{
public static readonly DependencyProperty ScrollToTopProperty =
DependencyProperty.RegisterAttached
(
"ScrollToTop",
typeof(bool),
typeof(ScrollToTopBehavior),
new UIPropertyMetadata(false, OnScrollToTopPropertyChanged)
);
public static bool GetScrollToTop(DependencyObject obj)
{
return (bool)obj.GetValue(ScrollToTopProperty);
}
public static void SetScrollToTop(DependencyObject obj, bool value)
{
obj.SetValue(ScrollToTopProperty, value);
}
private static void OnScrollToTopPropertyChanged(DependencyObject dpo,
DependencyPropertyChangedEventArgs e)
{
ItemsControl itemsControl = dpo as ItemsControl;
if (itemsControl != null)
{
DependencyPropertyDescriptor dependencyPropertyDescriptor =
DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(ItemsControl));
if (dependencyPropertyDescriptor != null)
{
if ((bool)e.NewValue == true)
{
dependencyPropertyDescriptor.AddValueChanged(itemsControl, ItemsSourceChanged);
}
else
{
dependencyPropertyDescriptor.RemoveValueChanged(itemsControl, ItemsSourceChanged);
}
}
}
}
static void ItemsSourceChanged(object sender, EventArgs e)
{
ItemsControl itemsControl = sender as ItemsControl;
EventHandler eventHandler = null;
eventHandler = new EventHandler(delegate
{
if (itemsControl.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
ScrollViewer scrollViewer = GetVisualChild<ScrollViewer>(itemsControl) as ScrollViewer;
scrollViewer.ScrollToTop();
itemsControl.ItemContainerGenerator.StatusChanged -= eventHandler;
}
});
itemsControl.ItemContainerGenerator.StatusChanged += eventHandler;
}
}
而且GetVisualChild的实现
private T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
迟到的回答:
一个简单的解决方法是添加事件处理程序TargetUpdated
事件,并设置在ItemsSource
NotifyOnTargetUpdated=True
结合:
<ListBox x:Name="listBox"
ItemsSource="{Binding MySource, NotifyOnTargetUpdated=True}"
TargetUpdated="ListBox_TargetUpdated"/>
,并在事件处理程序,滚动到顶部项目:
private void ListBox_TargetUpdated(object sender, DataTransferEventArgs e)
{
if (listBox.Items.Count > 0)
{
listBox.ScrollIntoView(listBox.Items[0]);
}
}
改进弗雷德里克Hedblad的回答工作与ObservableCollection:
public static class ItemsControlAttachedProperties
{
#region ScrollToTopOnItemsSourceChange Property
public static readonly DependencyProperty ScrollToTopOnItemsSourceChangeProperty =
DependencyProperty.RegisterAttached(
"ScrollToTopOnItemsSourceChange",
typeof(bool),
typeof(ItemsControlAttachedProperties),
new UIPropertyMetadata(false, OnScrollToTopOnItemsSourceChangePropertyChanged));
public static bool GetScrollToTopOnItemsSourceChange(DependencyObject obj)
{
return (bool) obj.GetValue(ScrollToTopOnItemsSourceChangeProperty);
}
public static void SetScrollToTopOnItemsSourceChange(DependencyObject obj, bool value)
{
obj.SetValue(ScrollToTopOnItemsSourceChangeProperty, value);
}
static void OnScrollToTopOnItemsSourceChangePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var itemsControl = obj as ItemsControl;
if (itemsControl == null)
{
throw new Exception("ScrollToTopOnItemsSourceChange Property must be attached to an ItemsControl based control.");
}
DependencyPropertyDescriptor descriptor =
DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(ItemsControl));
if (descriptor != null)
{
if ((bool) e.NewValue)
{
descriptor.AddValueChanged(itemsControl, ItemsSourceChanged);
}
else
{
descriptor.RemoveValueChanged(itemsControl, ItemsSourceChanged);
}
}
}
static void ItemsSourceChanged(object sender, EventArgs e)
{
var itemsControl = sender as ItemsControl;
DoScrollToTop(itemsControl);
var collection = itemsControl.ItemsSource as INotifyCollectionChanged;
if (collection != null)
{
collection.CollectionChanged += (o, args) => DoScrollToTop(itemsControl);
}
}
static void DoScrollToTop(ItemsControl itemsControl)
{
EventHandler eventHandler = null;
eventHandler =
delegate
{
if (itemsControl.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
var scrollViewer = GetVisualChild<ScrollViewer>(itemsControl);
scrollViewer.ScrollToTop();
itemsControl.ItemContainerGenerator.StatusChanged -= eventHandler;
}
};
itemsControl.ItemContainerGenerator.StatusChanged += eventHandler;
}
static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < numVisuals; i++)
{
var v = (Visual) VisualTreeHelper.GetChild(parent, i);
child = v as T ?? GetVisualChild<T>(v);
if (child != null)
{
break;
}
}
return child;
}
#endregion
}
当您格式化控件时,您选择一个单元格的范围作为选择选择是t母鸡在列表框中列出。您还可以选择一个单元格作为所选选项的链接,其中将显示一个数字,具体取决于列表中选择的位置。列表中的第一个为1,第二个为2等该代码是很简单: -
范围( “A1”)选择
选择= 1名
更改( “A1”)你有联系 细胞,改变1中的位置你想要选择的列表。
作为链接的单元格引用可以双向使用 - 如果更改所选内容,单元格中的数字会发生变化,如果更改单元格中的数字,突出显示的选择内容会发生变化。
我理解你的问题是否正确或者你在找别的东西? – 2011-01-26 12:35:02
@Meleak谢谢!该方法将会有用。我实际上已经将问题追踪到了我的ListBox使用的VirtualizingTilePanel,我从http://blogs.msdn.com/b/dancre/archive/2006/02/16/implementing-a-virtualizingpanel-part -4-,goods.aspx。通过滚动到底部,可以在示例下载中复制问题,然后用包含单个项目的集合替换绑定的集合。视图变为空白,直到用鼠标滚轮向上滚动。 – devdigital 2011-01-26 13:12:35