我目前有一个ListBox,其ItemsSource集合绑定到我的viewmodel上的一个属性,类型为IEnumerable。当preoprty的引用发生更改时,ListBox会按预期更新,但是我有一个问题,如果我有大量项目并滚动到ListBox的底部,然后将引用更改为包含例如1项的另一个集合,ListBox视图为空,不显示滚动条。然后我必须用鼠标滚轮向上滚动列表框,直到看到1个项目。
因此,我认为我所追求的是,只要ItemsSource属性发生更改,就会将ListBox的滚动位置重置为顶部,这样无论收集的大小,都会显示一些内容。< / p>
答案 0 :(得分:21)
我无法重现您的问题(对我来说,ListBox
在更改ItemsSource
时会滚动到新集合中的最后一项。无论如何,每次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;
}
答案 1 :(得分:7)
迟到的回答:
一个简单的解决方案是为TargetUpdated
事件添加事件处理程序,并在NotifyOnTargetUpdated=True
绑定上设置ItemsSource
:
<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]);
}
}
答案 2 :(得分:1)
试试这个:
if (listBox.Items.Count > 0) {
listBox.ScrollIntoView(listBox.Items[0]);
}
答案 3 :(得分:0)
改进了Fredrik Hedblad使用ObservableCollection的答案:
std::cout << 0 << " " << is_small<0>() << std::endl;
答案 4 :(得分:0)
格式化控件时,选择一系列单元格作为选择选项,然后在列表框中列出。您还可以选择一个单元格作为所选选项的链接,其中将显示一个数字,具体取决于列表中选择的位置。列表中的第一个为1,第二个为2等。代码非常简单: -
范围( “A1”)选择
选择= 1
将(“A1”)更改为您已链接的单元格 并将1更改为您想要选择的列表中的位置。
作为链接的单元格引用是双向的 - 如果更改选择,单元格中的数字会更改,如果更改单元格中的数字,则突出显示的选择会更改。