2009-10-23 9 views
7

Possiedo un numero ItemsControl che corrisponde a un valore ObservableCollection. Ho questo metodo nel codice dietro il quale aggiunge un nuovo modello alla lista. Vorrei quindi scorrere la nuova voce (in fondo alla lista) in vista.Visualizzazione di un nuovo elemento in ItemsControl in visualizzazione

Penso che la dimensione di ItemsControl non sia stata ancora aggiornata quando sto interrogando la dimensione, dal momento che lo ActualHeight prima e dopo l'aggiunta del modello è lo stesso. L'effetto di questo codice è quello di scorrere fino a un punto leggermente al di sopra del nuovo elemento.

Come faccio a sapere quale sarà il nuovo ActualHeight?

Ecco il mio codice:

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

risposta

5

Credo che è necessario chiamare BringIntoView sul contenitore oggetto, non l'ItemsControl stesso:

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

EDIT: in realtà questo non lo fa lavoro, perché a questo punto, il contenitore dell'elemento non è stato ancora generato ... Probabilmente potresti gestire l'evento StatusChanged dello ItemContainerGenerator. Ho provato il seguente codice:

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; 
    } 
} 

Tuttavia non funziona o ... per qualche ragione, ContainerFromItem restituisce ancora nulla dopo lo stato passa a ContainersGenerated, e non ho idea del perché: S


MODIFICA: OK, ho capito ora ... questo era a causa della virtualizzazione: i contenitori vengono generati solo quando devono essere visualizzati, quindi non vengono generati contenitori per oggetti nascosti. Se si disattiva la virtualizzazione per ItemsControl (VirtualizingStackPanel.IsVirtualizing="False"), la soluzione sopra funziona correttamente.

+0

DocumentElements.ItemContainerGenerator.ContainerFromItem (modello) restituisce null? Non penso che la Vista sia stata ancora aggiornata al nuovo elemento nell'origine dati. –

+0

ah, sì, ho dimenticato che ... ma comunque, se il contenitore non è ancora in ItemsControl, non è possibile scorrere ad esso: S –

+0

vedere la mia risposta aggiornata –