2010-08-31 14 views
6

Dado el siguiente código XAML que con un ListControl como el comportamiento:WPF: listas de enlaces en XAML: ¿cómo puede un elemento conocer su posición en la lista?

<StackPanel> 
     <ItemsControl Name="_listbox" ItemsSource="{Binding ElementName=_userControl, Path=DataContext}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <DockPanel> 
         ... 
        </DockPanel> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
    </StackPanel> 

Dado que la lista puede ser larga (100-200 material), y los artículos un aspecto similar, creo que sería muy útil para el usuario durante el desplazamiento si cada elemento mostraría su posición en la lista. ¿Cómo podría un elemento de la plantilla conocer su propia posición en la lista?

Respuesta

5

Aquí hay una solución de hackeo. Podemos usar Value Conversion con DataBinding. Así que el primer paso es declarar nuestra ValueConvertor:

public class ListItemToPositionConverter : IValueConverter 
    { 
     #region Implementation of IValueConverter 

     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      var item = value as ListBoxItem; 
      if (item != null) 
      { 
       var lb = FindAncestor<ListBox>(item); 
       if (lb != null) 
       { 
        var index = lb.Items.IndexOf(item.Content); 
        return index; 
       } 
      } 
      return null; 
     }    

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 

     #endregion 
    } 

Declarar donde desea que este método estático con el fin de obtener ListBox padres:

public static T FindAncestor<T>(DependencyObject from) where T : class 
     { 
      if (from == null) 
       return null; 

      var candidate = from as T; 
      return candidate ?? FindAncestor<T>(VisualTreeHelper.GetParent(from)); 
     } 

Luego, en ListBox.Resources declarar nuestro convertidor de la siguiente manera:

<ListBox.Resources> 
       <YourNamespace:ListItemToPositionConverter x:Key="listItemToPositionConverter"/> 
      </ListBox.Resources> 

Y, por último - DataTemplate:

<ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel> 
         <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Converter={StaticResource listItemToPositionConverter}}"/> 
         <Label Content="{Binding Path=DisplayName}"></Label> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 

Nota: En este ejemplo, los elementos se numerarán comenzando por 0 (cero), puede cambiarlo en el método Convertir agregando 1 al resultado.

Espero que esto ayude ...

0

Según MSDN Magazine artículo "Charting with DataTemplates":

[...] DataTemplate tendría acceso al índice del elemento de datos en particular en la colección. Pero es bastante fácil de incluir esta información en el objeto de negocio [...]

Por lo tanto, a menos que hubiera un cambio en .NET 4, no hay un "índice de este artículo" a menos que la propiedad se incluye explícitamente en el modelo.

Cuestiones relacionadas