web-dev-qa-db-ja.com

WPF ListBoxスクロールして自動的に終了

私のアプリケーションには、アイテムを含むListBoxがあります。アプリケーションはWPFで記述されています。

最後に追加されたアイテムに自動的にスクロールするにはどうすればよいですか?新しいアイテムが追加されたときに、ScrollViewerをリストの最後に移動する必要があります。

ItemsChangedのようなイベントはありますか? (SelectionChangedイベントを使用したくない)

36
niao

これを試して:

lstBox.SelectedIndex = lstBox.Items.Count -1;
lstBox.ScrollIntoView(lstBox.SelectedItem) ;

MainWindowで、これはリストの最後のアイテムを選択してフォーカスします!

38
Oz Mayt

これを行う最も簡単な方法:

if (VisualTreeHelper.GetChildrenCount(listView) > 0)
{
    Border border = (Border)VisualTreeHelper.GetChild(listView, 0);
    ScrollViewer scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
    scrollViewer.ScrollToBottom();
}

ListViewおよびListBoxコントロールに対して常に機能します。このコードをlistView.Items.SourceCollection.CollectionChangedイベントに添付すると、完全に自動化された自動スクロールの動作が得られます。

30
Mateusz Myślak

listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]);は、重複するアイテムがない場合にのみ機能することに注意してください。同じ内容のアイテムがある場合、最初の検索までスクロールダウンします。

ここに私が見つけた解決策があります:

ListBoxAutomationPeer svAutomation = (ListBoxAutomationPeer)ScrollViewerAutomationPeer.CreatePeerForElement(myListBox);

IScrollProvider scrollInterface = (IScrollProvider)svAutomation.GetPattern(PatternInterface.Scroll);
System.Windows.Automation.ScrollAmount scrollVertical = System.Windows.Automation.ScrollAmount.LargeIncrement;
System.Windows.Automation.ScrollAmount scrollHorizontal = System.Windows.Automation.ScrollAmount.NoAmount;
//If the vertical scroller is not available, the operation cannot be performed, which will raise an exception. 
if ( scrollInterface.VerticallyScrollable )
    scrollInterface.Scroll(scrollHorizontal, scrollVertical);
28
NovaLogic

最善の解決策は、このコレクションがコンテンツビューアー向けに特別に設計されたListBoxコントロール内でItemCollectionオブジェクトを使用することです。最後のアイテムを選択し、カーソル位置の参照を保持するための事前定義されたメソッドがあります。

myListBox.Items.MoveCurrentToLast();
myListBox.ScrollIntoView(myListBox.Items.CurrentItem);
20
Givanio

これまでに提示されたアプローチとは少し異なるアプローチ。

ScrollViewerScrollChangedイベントを使用して、ScrollViewerの内容が大きくなるのを監視できます。

private void ListBox_OnLoaded(object sender, RoutedEventArgs e)
{
    var listBox = (ListBox) sender;

    var scrollViewer = FindScrollViewer(listBox);

    if (scrollViewer != null)
    {
        scrollViewer.ScrollChanged += (o, args) =>
        {
            if (args.ExtentHeightChange > 0)
                scrollViewer.ScrollToBottom();
        };
    }
}

これにより、ListBoxItemsSource変更へのバインドに関する問題を回避できます。

ScrollViewerは、ListBoxがデフォルトのコントロールテンプレートを使用していると仮定せずに見つけることもできます。

// Search for ScrollViewer, breadth-first
private static ScrollViewer FindScrollViewer(DependencyObject root)
{
    var queue = new Queue<DependencyObject>(new[] {root});

    do
    {
        var item = queue.Dequeue();

        if (item is ScrollViewer)
            return (ScrollViewer) item;

        for (var i = 0; i < VisualTreeHelper.GetChildrenCount(item); i++)
            queue.Enqueue(VisualTreeHelper.GetChild(item, i));
    } while (queue.Count > 0);

    return null;
}

次に、これをListBoxLoadedイベントに添付します。

<ListBox Loaded="ListBox_OnLoaded" />

これは、より汎用的にするために、添付プロパティに簡単に変更できます。

5
Scroog1

listBox.ScrollIntoView(listBox.Items [listBox.Items.Count-1]);

4
JOKe

私にとって、最も簡単な作業方法はこれでした:(バインドなし)

 private void WriteMessage(string message, Brush color, ListView lv)
        {

            Dispatcher.BeginInvoke(new Action(delegate
            {
                ListViewItem ls = new ListViewItem
                {
                    Foreground = color,
                    Content = message
                };
                lv.Items.Add(ls);
                lv.ScrollIntoView(lv.Items[lv.Items.Count - 1]);
            }));
        }

クラスを作成したり、xamlを変更したりする必要はありません。このメソッドでメッセージを書き込むだけで、自動的にスクロールします。

ただ電話する

myLv.Items.Add(ls);
myLv.ScrollIntoView(lv.Items[lv.Items.Count - 1]);

たとえば、私のために動作しないでください。

1
Matheus Stumpf

ListBox.ScrollIntoView() メソッドを試すことができますが、いくつかのケースでは 問題 があります...

Tamir Khasonの例を次に示します。 WPFの自動スクロールListBox

0
Anvaka