2010-03-13 3 views
3

Est-il possible de continuer les styles d'altération dans une grille même s'il n'y a pas d'éléments?Continuer l'altération de la grille de WPF

alt text http://i42.tinypic.com/xla5gm.jpg

Comme vous pouvez le voir, après le dernier élément, le motif s'arrête.

+0

Voir quel modèle? – TFD

+0

Gris foncé, gris clair, gris foncé, gris clair – ErikTJ

+0

J'aime vraiment ce style! De toute façon, vous pouvez poster cela à pastebin.com et envoyez-moi le lien. – Kredns

Répondre

2

Oui, WPF fournit une manière plutôt élégante de l'implémenter parce que son mécanisme de modèle vous permet de remplir la zone inutilisée dans un GridView avec ce que vous voulez.

Tout ce que vous devez faire est de modifier le modèle ListView pour peindre la partie inutilisée de la avec un VisualBrush qui se compose généralement de deux GridViewItems empilés verticalement (dans le cas général, il sera AlternationCountGridViewItems). La seule complexité est de choisir la couleur de départ lors de la peinture de la section inutilisée de la ScrollViewer

Ceci est calculé comme Items.Count modulo AlternationCount. La solution consiste à créer un simple Control qui fait ce calcul et l'utiliser dans notre modèle ListView. Pour le bien de mon explication, j'appellerai le contrôle "ContinueAlternation".

Le modèle ListView qui serait principalement le modèle par défaut avec un contrôle local:ContinueAlternation ajouté sous le ScrollViewer en utilisant un DockPanel, comme ceci:

<ControlTemplate TargetType="{x:Type ListView}"> 
    <Border BorderThickness="{TemplateBinding BorderThickness}" 
      BorderBrush="{TemplateBinding BorderBrush}" 
      Background="{TemplateBinding Background}" 
      SnapsToDevicePixels="True"> 
    <DockPanel> 
     <ScrollViewer DockPanel.Dock="Top" 
        Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}" 
        Padding="{TemplateBinding Padding}"> 
     <ItemsPresenter SnapsToDevicePixels="True" /> 
     </ScrollViewer> 

     <local:ContinueAlternation 
     ItemContainerStyle="{TemplateBinding ItemContainerStyle}" 
     AlternationCount="{TemplateBinding AlternationCount}" 
     ItemsCount="{Binding Items.Count, 
          RelativeSource={RelativeSource TemplatedParent}}" /> 

    </DockPanel> 
    </Border> 
</ControlTemplate> 

Le contrôle ContinueAlternation sera affiché comme Rectangle peint avec un carrelage VisualBrush contenant un ItemsControl qui montre des lignes fictives, comme suit:

<ControlTemplate TargetType="{x:Type local:ContinueAlternation}"> 
    <Rectangle> 
    <Rectangle.Fill> 

     <VisualBrush TileMode="Tile" Stretch="None" 
        ViewPortUnits="Absolute" 
        ViewPort="{TemplateBinding ViewportSize}"> 

     <ItemsControl x:Name="PART_ItemsControl" 
         ItemsSource="{Binding}" /> 
     </VisualBrush> 
    </Rectangle.Fill> 
    </Rectangle> 
</ControlTemplate> 

Le DataContext ici sera un tableau de ListViewItem factice généré en code-behind de la donnée AlternationCount et ItemsCount:

public class ContinueAlternation 
{ 
    public Style ItemsContainerStyle ... // Declare as DependencyProperty using propdp snippet 
    public int AlternationCount ... // Declare as DependencyProperty using propdp snippet 
    public int ItemsCount ... // Declare as DependencyProperty using propdp snippet 

    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
    { 
    if(e.Property==ItemsContainerStyleProperty || 
     e.Property==AlternationCountProperty || 
     e.Property==ItemsCountProperty) 
    { 
     // Here is where we build the items for display 
     DataContext = 
     from index in Enumerable.Range(ItemsCount, 
             ItemsCount + AlternationCount) 
     select BuildItem(index % AlternationCount); 
    } 
    } 
    ListViewItem BuildItem(int alternationIndex) 
    { 
    var item = new ListViewItem { Style = ItemsContainerStyle }; 
    ItemsControl.SetAlternationIndex(item, alternationIndex); 
    return item; 
    } 

    protected override Size MeasureOverride(Size desiredSize) 
    { 
    var ic = (ItemsControl)GetTemplateChild("PART_ItemsControl"); 
    ic.Width = desiredSize.Width; 
    Size result = base.MeasureOverride(desiredSize); 
    ViewportSize = new Size(ic.DesiredSize); 
    return result; 
    } 
    public Size ViewportSize ... // Declare as DependencyProperty using propdp snippet 
} 

Notez que ce même code peut être écrit avec PropertyChangedCallback au lieu de OnPropertyChanged.

Vous devez également faire quelque chose pour vous assurer que les rangées vides ont la hauteur désirée. La manière la plus simple de le faire est de définir MinHeight ou Content dans votre ItemsContainerStyle. Alternativement ContinueAlternation pourrait définir la hauteur quand il construit chaque ListViewItem.

J'ai tapé tout ce code du haut de ma tête, mais il est similaire au code que j'ai écrit et utilisé auparavant, il devrait donc fonctionner essentiellement tel quel.