2010-11-22 21 views
1

Gibt es eine Möglichkeit, ein ListView vertikal zu scrollen, während Daten über eine Bindung an die ItemsSource-Eigenschaft der ListView aktualisiert werden? Ich kann anscheinend keine Eigenschaft in der ListView oder dem ihr zugrunde liegenden GridView-Steuerelement finden, um das gewünschte Ergebnis zu erzielen. Ich möchte es scrollen, damit die neuesten Informationen für den Benutzer immer sichtbar sind. Eine Bildlaufleiste wird bereits angezeigt, wenn die Zeilen zum Steuerelement hinzugefügt werden, die aktuellste Zeile jedoch nicht angezeigt wird.WPF-ListView: Benutzerdefiniertes Scrolling-Verhalten

Sollte ich einen anderen Steuerungstyp mit automatischer Bildlauffunktion verwenden? Ich habe nur zwei Spalten: eine enthält DateTimes und die andere enthält eine einfache Zeichenfolge. Ich fange an zu denken, dass meine Kontrollwahl vielleicht zu begrenzt ist.

Meine XAML sieht ungefähr wie folgt aus:

<ListView ItemsSource="{Binding Updates}"> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn Header="Timestamp" DisplayMemberBinding="{Binding TimeStamp}"/> 
      <GridViewColumn DisplayMemberBinding="{Binding UpdateString}" /> 
     </GridView> 
    </ListView.View> 
</ListView> 
+0

@ Antwort Daniel In Anbetracht suchen Sie die Gridview * in der Lage zu machen Scrollen * wenn benötigt, dh. Wenn es mehr als einen Bildschirm mit Daten enthält, oder möchten Sie, dass das * Scrollen selbst * automatisch erfolgt, so dass ältere Daten aus dem Ansichtsfenster verschoben werden und neuere Daten beim Hinzufügen gescrollt werden? @Daniel antwortet auf die erste, aber die zweite benötigt Animationen/'EventTriggers'. :) –

+0

Guter Punkt, ich hätte klarstellen sollen. Ich brauche es, um zu blättern, wenn mehr als ein Bildschirm mit Daten vorhanden ist, und blättern dann, wenn Daten die GridView füllen. Ich werde diese Informationen hinzufügen. – jlafay

Antwort

2

Ich habe gefunden, um das ScrollViewer-Objekt ListView zu offenbaren, Scrollen zu manipulieren. Mein DataContext enthält eine Sammlung, die von ObservableCollection abgeleitet ist, und in dem Code, den ich hinterlegte, verband ich einen Eventhandler mit dem Ereignis CollectionChanged. Ich habe eine Decorator verwendet, um das erste Kind der ListView (der Grenze) zu exponieren, und es ist Kind ScrollViewer. Von dort rufe ich die ScrollToBottom() Methode an, um das gewünschte Verhalten zu erreichen.

In der Code-behind für meine Ansicht, die die ListView enthält, ist dies, wie es

MyViewModel viewModel = DataContext as MyViewModel; 

viewModel.MyCollection.CollectionChanged += (sender,e) => 
{ 
    if(e.NewItems != null) 
    { 
     Decorator border = VisualTreeHelper.GetChild(SummaryListView, 0) as Decorator; 
     ScrollViewer scroll = border.Child as ScrollViewer; 
     scroll.ScrollToBottom(); 
    } 
}; 

Ich fand codiert ist, wie die ScrollViewer auf Anshulee's WindowsClient blog post auszusetzen.

Bearbeiten Zuvor habe ich überprüft, ob die maximale Anzahl der Elemente in der benutzerdefinierten Sammlung erfüllt war und dann nach unten gescrollt. Bei anderen Bildschirmauflösungen funktioniert das nicht so gut, da die App möglicherweise 15 Zeilen im Format ListView auf einer Maschine und 25 Zeilen in einer anderen Maschine anzeigt. So habe ich es jetzt immer nach unten scrollen, um das neueste Objekt in Sicht zu bringen.

1

Sie ein Scroll verwenden soll, wird es automatisch scrollen, wenn sein Inhalt benötigt (Sie können auch angeben, ob Sie immer horizontal oder vertikal blättern wollen unabhängig davon, wo sie gebraucht wird oder nicht, und einige andere Dinge auch)

<ScrollViewer> 
    <GridView> 
     <!-- gridview definition --> 
    <GridView> 
</ScrollViewer> 

weitere Informationen über MSDN

+0

Leider funktioniert das nicht für mich, weil die GridView-Header außerhalb der Ansicht scrollen. – jlafay

+0

Irgendwie könnte ich nur die Elemente und nicht die gesamte GridView umhüllen. Ich möchte vermeiden, den Header aus dem Blickfeld zu scrollen. – jlafay

0

ich bin mir ziemlich sicher, dass th an einem VirtualizingStackPanel wird unter den Abdeckungen verwendet ... was bedeutet, dass die Elemente nicht existieren, bis sie benötigt werden. Wenn Sie also 15000 Elemente haben, ist es nicht sinnvoll, diese 15000 Elemente vorher zu rendern.

Ein einfacherer Ansatz kann sein, eine Sortierung zu erzwingen, damit die neuesten Daten oben bleiben. Es wird Ihnen dann den Anschein geben, dass Sie Objekte nach unten schieben, aber sie werden die ältesten Elemente sein, so dass das Scrollen, um sie zu sehen, keine Rolle spielt, es sei denn, der Benutzer initiiert sie.

0

Ein Listview hat eine Methode namens ScrollIntoView(object item).

Dies wird die Listview zu der Position, wo das angegebene Element ist, scrollen.

Wenn Sie eine Sammlung, die auf die Listview binded ist, können Sie diese Methode aufrufen, wenn Ihre Sammlung geändert hat, so etwas wie:

private void myCollectionChanged() 
{ 
    myListView.ScrollIntoView(myCollection.Last()); 
} 
+0

Ich habe diese Methode auch ausprobiert, sie scrollt nicht zum untersten Punkt. Meine angenommene Antwort (und die, die ich angegeben habe) ist, was in meiner Bewerbung funktioniert hat. – jlafay

+0

Sind Sie sicher? Weil es in meiner Anwendung funktioniert. – Flagbug

+0

Ja, denn das wäre viel einfacher als das, was ich tun musste. Ich bevorzuge einfache und lesbare, um die Komplexität zu minimieren. – jlafay

Verwandte Themen