2009-10-23 17 views
7

Tengo un ItemsControl que está enlazado a un ObservableCollection. Tengo este método en el código detrás del cual agrega un nuevo modelo a la lista. Luego me gustaría desplazar el nuevo elemento (en la parte inferior de la lista) para ver.Desplazar un nuevo elemento en ItemsControl en la vista

Creo que el tamaño del ItemsControl aún no se ha actualizado cuando consulto el tamaño, ya que el ActualHeight antes y después de la adición del modelo es el mismo. El efecto de este código es desplazarse a un punto ligeramente por encima del nuevo elemento.

¿Cómo podría saber cuál va a ser el nuevo ActualHeight?

Aquí está mi código:

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

Respuesta

5

Creo que es necesario llamar a BringIntoView en el envase artículo, no el propio ItemsControl:

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

EDIT: en realidad este no lo hace trabajo, porque en este punto, el contenedor de elementos aún no se ha generado ... Probablemente podría manejar el evento StatusChanged del ItemContainerGenerator. He intentado el siguiente código:

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

Sin embargo, no funciona bien ... por alguna razón, todavía ContainerFromItem devuelve NULL después de los cambios de estado a ContainersGenerated, y no tengo ni idea de por qué: S


EDITAR: OK, ahora entiendo ... esto fue por la virtualización: los contenedores se generan solo cuando deben mostrarse, por lo que no se generan contenedores para elementos ocultos. Si desactiva la virtualización para ItemsControl (VirtualizingStackPanel.IsVirtualizing="False"), la solución anterior funciona bien.

+0

DocumentElements.ItemContainerGenerator.ContainerFromItem (model) devuelve nulo? No creo que la Vista se haya actualizado aún al nuevo elemento en la fuente de datos. –

+0

ah, sí, me olvidé de eso ... pero de todos modos, si el contenedor aún no está en ItemsControl, no puede desplazarse a él: S –

+0

ver mi respuesta actualizada –

Cuestiones relacionadas