2010-08-06 2 views
6

J'essaie de créer une liste déroulante de blocs de texte assez volumineux. Je veux qu'il y ait une barre de défilement verticale pour tous les montrer, et s'ils débordent d'une certaine taille, je veux qu'ils affichent une ellipse. En fait, tout cela fonctionne plutôt bien.Obtention de la virtualisation de l'interface utilisateur avec ItemsControl dans Silverlight

J'ai la XAML Silverlight suivante:

<Grid x:Name="LayoutRoot" MaxWidth="500" MinWidth="100" 
    MaxHeight="500" MinHeight="100"> 
    <Grid.DataContext> 
     <app:MainPageViewModel/> 
    </Grid.DataContext> 
    <ScrollViewer> 
    <ItemsControl ItemsSource="{Binding TextItems}" Margin="0,20,0,20"> 
     <ItemsControl.ItemTemplate><DataTemplate> 
      <Border MaxHeight="175" Margin="0,0,0,18" CornerRadius="5"> 
       <TextBlock Margin="2" TextTrimming="WordEllipsis" 
        TextWrapping="Wrap" Text="{Binding}"/> 
      </Border> 
     </DataTemplate></ItemsControl.ItemTemplate> 
    </ItemsControl> 
    </ScrollViewer> 
</Grid> 

Mon problème est que cette disposition n'utilise pas la virtualisation de l'interface utilisateur, comme un VirtualizingStackPanel. Donc c'est assez lent. Quel est le meilleur moyen d'intégrer la virtualisation de l'interface utilisateur dans cette mise en page? J'ai essayé une demi-douzaine de façons différentes et rien n'a vraiment bien fonctionné.

J'ai réussi à obtenir ce fonctionnement dans un ListBox car il semble prendre en charge la virtualisation dès le départ. Cependant, je préférerais utiliser ItemsControl car je ne veux pas que ces choses soient sélectionnables, et je ne veux pas le style qui accompagne un ListBox.

Cela Silverlight 4.

Répondre

15

Il y a quelques choses que vous devez faire pour faire ce travail.

  1. Réglez le ItemsPanelTemplate pour votre ItemsControl à un VirtualizingStackPanel.
  2. Incorporer le ScrollViewer à l'intérieur un ControlTemplate pour votre ItemsControl au lieu de simplement en l'enveloppant autour de l'extérieur.
  3. Assurez-vous que ItemsControl a une hauteur fixe afin que le système de mise en page puisse déterminer le nombre d'éléments dont il a besoin pour remplir la fenêtre. (On dirait que vous faites déjà cela en mettant ItemsControl dans une grille - qui permettra au système de mise en page pour déterminer la hauteur alloted pour le contrôle)

Voici l'exemple le plus simple je pourrais trouver de ce travail :

<ItemsControl ItemsSource="{Binding TextItems}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <VirtualizingStackPanel /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.Template> 
      <ControlTemplate TargetType="ItemsControl"> 
       <Border> 
        <ScrollViewer> 
         <ItemsPresenter/> 
        </ScrollViewer> 
       </Border> 
      </ControlTemplate> 
     </ItemsControl.Template> 
    </ItemsControl> 
+0

Qui a fonctionné comme un charme Steve. Donc la principale différence entre votre solution et ce que j'essayais de faire est que vous avez utilisé ItemsControl.Template pour ajouter dans le ScrollViewer, alors que j'essayais juste de mettre un ScrollViewer à l'extérieur du contrôle. Pouvez-vous expliquer pourquoi le vôtre fonctionne et ce que j'essayais de faire ne fonctionne pas? Cela pourrait m'aider à mieux comprendre la solution. – RationalGeek

+1

Super, content que ça a marché pour vous. Fondamentalement, ce qui se passe est que si vous placez un ScrollViewer autour de l'extérieur de ItemsControl alors le moteur de mise en page rendra l'ItemsControl entier - il générera des conteneurs d'éléments pour tous les éléments du contrôle. Le ScrollViewer ne fait que limiter la vue à une petite partie de ItemsControl, mais l'ensemble ItemsControl avec tous les éléments existe en mémoire. La seconde méthode, en plaçant le ScrollViewer dans le modèle, donne à ItemsControl la possibilité de limiter le nombre de conteneurs d'éléments qu'il crée - il créera seulement assez pour remplir l'espace disponible. –

+0

Cela a du sens. Merci encore! – RationalGeek

Questions connexes