2012-05-10 18 views
5

Estoy intentando crear una aplicación de referencia Win8 Metro para listas virtualizadas. Al hacer algunas lecturas (muy dispersas), descubrí que la forma recomendada de hacerlo es a través de la interfaz ISupportIncrementalLoading.ISupportIncrementalLoading solo se dispara una vez

Tengo un problema con mi aplicación de referencia, donde el método LoadMoreItemsAsync se llama una vez, pero no se vuelve a llamar, aunque mi propiedad HasmoreItems está codificada para devolver True.

Lo que el siguiente código debe hacer es cargar 40 elementos, luego cargar 'x' número a la vez. Lo que sucede es que carga los primeros 40 elementos, luego se le pide que cargue 42 más, y luego nunca se le pide que cargue nuevamente.

He aquí las partes pertinentes de mi código:

XAML

<Grid Background="{StaticResource ApplicationPageBackgroundBrush}"> 
    <ListView ItemsSource="{Binding Items}" Width="800" HorizontalAlignment="Left" Margin="12"> 
     <ListView.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Title}" Foreground="White"/> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 

</Grid> 

ViewModel y clases de apoyo:

public class MainViewModel : ViewModelBase 
{ 

    public MyIncrementalCollection Items { get; set; } 

    public MainViewModel() 
    { 

     Items = new MyIncrementalCollection(); 



     for (int i = 0; i < 40; i++) 
     { 
      Items.Add(new MyData {Title = string.Format("Item: {0}", i)}); 
     } 
    } 
} 

public class MyData 
{ 
    public string Title { get; set; } 
} 

public class MyIncrementalCollection : ObservableCollection<MyData>, ISupportIncrementalLoading 
{ 
    public bool HasMoreItems 
    { 
     get 
     { 
      return true; 
     } 
    } 

    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count) 
    { 
     return 
      (IAsyncOperation<LoadMoreItemsResult>) 
      AsyncInfo.Run((System.Threading.CancellationToken ct) => LoadDataAsync(count)); 
    } 

    private async Task<LoadMoreItemsResult> LoadDataAsync(uint count) 
    { 

     for (int i = 0; i < count; i++) 
     { 
      this.Add(new MyData { Title = string.Format("Item: {0}, {1}", i, System.DateTime.Now) }); 
     } 

     var ret = new LoadMoreItemsResult {Count = count}; 

     return ret; 
    } 


} 

}

Respuesta

2

El problema es que su método LoadDataAsync (recuento uint) falta el operador lo esperan y debido a que se ejecute de forma sincrónica. Tuve un problema similar. La virtualización de datos me funcionaba mientras recibía algunas carpetas de la biblioteca, pero se activó solo una vez cuando intenté cargar una colección de elementos personalizados.

Usé una solución, no muy elegante, pero funcionó. Modificar su LoadDataAsync método como este:

private async Task<LoadMoreItemsResult> LoadDataAsync(uint count) 
{ 
    Task task = Task.Delay(1); 
    await task; 

    for (int i = 0; i < count; i++) 
    { 
    Add(new MyData { Title = string.Format("Item: {0}, {1}", i, System.DateTime.Now) }); 
    } 

    return new LoadMoreItemsResult {Count = count}; 
} 
+0

Bueno, mierda. Eso funciona. Me pregunto si arreglarán esto en el RC ... – Robaticus

0

La interfaz de usuario única llamará HasMoreItems cuando se siente necesita hacerlo. Si tiene suficientes elementos para llenar el área actualmente visible, entonces no buscará más elementos. Si comienza a desplazarse hacia el final de la lista, comprobará si hay más elementos (y si hay una llamada a LoadMoreItemsAsync).

Dicho sea de paso se puede simplificar el código en LoadMoreItemsAsync a

public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count) 
{ 
    return LoadDataAsync(count).AsAsyncOperation(); 
} 
+0

Gracias por la simplificación. El problema aquí es que, cuando me desplazo, la carga solo se llama una vez. Puedo llegar hasta el final de la lista, después de la primera carga de elementos adicionales, y nunca vuelve a dispararse. – Robaticus

+0

Ok, ¿es la xaml la totalidad de su vista? Otros problemas pueden incluir si tiene su ListView dentro de ScrollViewer, no obtendrá activadores de virtualización de datos (ya que depende de usar el ScrollViewer interno de Vistas de lista). –

+0

Esa es la totalidad, con la excepción de la etiqueta '' adjunta. ¿Tengo que hacer algo específico en mi acción de carga asincrónica para decirle al ListView que he terminado de cargar, para que no vuelva a dispararse? Supuse que el retorno de LoadMoreItemsResult sería todo lo que realmente necesitaba. – Robaticus

Cuestiones relacionadas