2009-10-23 5 views
7

Ich habe eine ItemsControl, die zu einem ObservableCollection datengebunden ist. Ich habe diese Methode in dem Code, hinter dem ein neues Modell der Liste hinzugefügt wird. Ich würde dann gerne den neuen Gegenstand (am Ende der Liste) in Sicht sehen.Scrollen Sie ein neues Element in einem ItemsControl in Sicht

Ich denke, die Größe der ItemsControl ist noch nicht aktualisiert, wenn ich die Größe abfrage, da die ActualHeight vor und nach der Hinzufügung des Modells das gleiche ist. Der Effekt dieses Codes besteht darin, zu einem Punkt etwas über dem neuen Element zu scrollen.

Wie würde ich wissen, was die neue ActualHeight wird?

Hier ist mein Code:

 ViewModel.CreateNewChapter(); 
     var height = DocumentElements.ActualHeight; 
     var width = DocumentElements.ActualWidth; 
     DocumentElements.BringIntoView(new Rect(0, height - 1, width, 1)); 

Antwort

5

Ich glaube, Sie BringIntoView auf dem Elementcontainer anrufen müssen, nicht die Items selbst:

var container = DocumentElements.ItemContainerGenerator.ContainerFromItem(model) as FrameworkElement; 
if (container != null) 
    container.BringIntoView(); 

EDIT: eigentlich tut dies nicht arbeiten, weil zu diesem Zeitpunkt der Artikel-Container noch nicht erstellt wurde ... Sie könnten wahrscheinlich das StatusChanged Ereignis der ItemContainerGenerator behandeln. Ich habe versucht, den folgenden Code:

public static class ItemsControlExtensions 
{ 
    public static void BringItemIntoView(this ItemsControl itemsControl, object item) 
    { 
     var generator = itemsControl.ItemContainerGenerator; 

     if (!TryBringContainerIntoView(generator, item)) 
     { 
      EventHandler handler = null; 
      handler = (sender, e) => 
      { 
       switch (generator.Status) 
       { 
        case GeneratorStatus.ContainersGenerated: 
         TryBringContainerIntoView(generator, item); 
         break; 
        case GeneratorStatus.Error: 
         generator.StatusChanged -= handler; 
         break; 
        case GeneratorStatus.GeneratingContainers: 
         return; 
        case GeneratorStatus.NotStarted: 
         return; 
        default: 
         break; 
       } 
      }; 

      generator.StatusChanged += handler; 
     } 
    } 

    private static bool TryBringContainerIntoView(ItemContainerGenerator generator, object item) 
    { 
     var container = generator.ContainerFromItem(item) as FrameworkElement; 
     if (container != null) 
     { 
      container.BringIntoView(); 
      return true; 
     } 
     return false; 
    } 
} 

aber es auch nicht ... aus irgendeinem Grund nicht funktioniert, ContainerFromItem noch null zurück, nachdem die Statusänderungen zu ContainersGenerated, und ich habe keine Ahnung, warum: S


EDIT: OK, ich verstehe jetzt ... das war wegen der Virtualisierung: die Container werden nur generiert, wenn sie angezeigt werden müssen, so dass keine Container für versteckte Elemente generiert werden. Wenn Sie die Virtualisierung für ItemsControl (VirtualizingStackPanel.IsVirtualizing="False") deaktivieren, funktioniert die obige Lösung einwandfrei.

+0

DocumentElements.ItemContainerGenerator.ContainerFromItem (Modell) gibt null zurück? Ich glaube nicht, dass die Ansicht noch auf das neue Element in der Datenquelle aktualisiert wurde. –

+0

ah, ja, ich habe das vergessen ... aber trotzdem, wenn der Container noch nicht im ItemsControl ist, kann man nicht scrollen: S –

+0

sehe meine aktualisierte Antwort –

Verwandte Themen