18

私は現在、ItemsSource コレクションが IEnumerable 型のビューモデルのプロパティにバインドされている ListBox を持っています。その preoprty の参照が変更されると、ListBox は期待どおりに更新されますが、アイテムの大きなコレクションがあり、ListBox の一番下までスクロールしてから、たとえば 1 つのアイテムを含む別のコレクションへの参照を変更すると、問題が発生します。の場合、ListBox ビューは空白で、スクロールバーは表示されません。次に、1 つの項目が表示されるまで、マウス ホイールでリストボックスを上にスクロールする必要があります。

したがって、私が後だと思うのは、ItemsSource プロパティが変更されるたびに、ListBox のスクロール位置を一番上にリセットする方法です。これにより、コレクションがどれほど大きくても小さくても常に何かが表示されます。

4

5 に答える 5

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;
}
于 2011-01-25T18:48:30.737 に答える
7

遅い答え:

簡単な解決策は、イベントのイベント ハンドラーを追加し、バインディングTargetUpdatedに設定することです。NotifyOnTargetUpdated=TrueItemsSource

<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]);
    }
}
于 2015-02-12T11:11:40.620 に答える
1

これを試して:

if (listBox.Items.Count > 0) {
    listBox.ScrollIntoView(listBox.Items[0]); 
}
于 2011-01-25T11:45:44.643 に答える