web-dev-qa-db-fra.com

ScrollViewer ne défile pas dans WPF

J'utilise un contrôle scrollviewer autour de mon panneau de pile qui contient un ItemsControl. Lorsqu'il y a beaucoup d'éléments dans le contrôle des éléments, il est supposé défiler, mais pour une raison quelconque, il suffit de couper les éléments. Voici le code: 

<StackPanel>
    <ScrollViewer CanContentScroll="True" VerticalScrollBarVisibility="Visible">
        <ItemsControl  Name="icEvents" Width="Auto" Height="100"  Background="AliceBlue" 
                       ItemsSource="{Binding Path=EventSources}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="Source:"/>
                        <TextBlock Text="{Binding Path=Source}" />
                        <TextBlock Text="Original Source:"/>
                        <TextBlock Text="{Binding Path=OriginalSource}" />
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</StackPanel>
30
azamsharp

Essayez une grille autour de votre ScrollViwer au lieu de StackPanel. Je pense que StackPanel fournira autant de hauteur que le contenu interne le souhaite, de sorte qu'ici la Scrollviwer ne fonctionne pas correctement car sa hauteur n'est pas limitée par son contrôle parent.

Vous pouvez comprendre le problème de l'exemple ci-dessous.

<StackPanel>
    <ScrollViewer>
        <ItemsControl >
            <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
            <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
            <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
            <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
            <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
        </ItemsControl>
    </ScrollViewer>
</StackPanel>

Le code ci-dessus est similaire au vôtre et il ne vous donne pas les barres de défilement. Mais voyez le code ci-dessous dans lequel je n'ai changé que la StackPanel en une Grid (Tout panneau respectant la taille de ses enfants en fonction de la taille des panneaux mais pas de la pile)

<Grid>
    <ScrollViewer>
        <ItemsControl >
            <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
            <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
            <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
            <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
            <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
        </ItemsControl>
    </ScrollViewer>
</Grid>

UPDATE: Mais si vous devez vraiment utiliser StackPanel, vous devrez peut-être définir la taille de votre ScrollViwer pour obtenir le défilement du contenu.

45
Jobi Joy

Vous devez corriger la hauteur de Scrollviewer, mais vous pouvez facilement vous lier à StackPanel ActualHeight:
(code testé)

<StackPanel Name="mypanel">
   <ScrollViewer Height="{Binding ElementName=mypanel, Path=ActualHeight}">
       <ItemsControl>
          <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" Width="200"/>
          <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
          <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" Width="200"/>
          <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
          <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" />
      </ItemsControl>
   </ScrollViewer>
</StackPanel>

Ou mieux encore, si vous ne pouvez pas changer le nom du StackPanel:

<StackPanel>
    <ScrollViewer Height="{Binding RelativeSource={RelativeSource FindAncestor, 
                        AncestorType={x:Type StackPanel}}, Path=ActualHeight}">
       <ItemsControl>
          <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" Width="200"/>
          <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
          <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" Width="200"/>
          <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
          <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" />
      </ItemsControl>
   </ScrollViewer>
</StackPanel>

Il s’agit d’un problème de type «Vous d’abord», le StackPanel demande la hauteur au ScrollViewer et le ScrollViewer demande au StackPanel la hauteur maximale possible.

23
Eduardo Molteni

La ItemsControl devrait contenir la ScrollViewer et non l'inverse. La seule chose que ScrollViewer connaît est la ItemsControl elle-même dans votre cas - elle ne connaît pas les éléments internes.

Essayez quelque chose comme ça:

<ItemsControl Name="icEvents" Width="Auto" Height="100"
    Background="AliceBlue"
    ItemsSource="{Binding Path=EventSources}">
    <ItemsControl.ItemTemplate>
        <DataTemplate> 
            <StackPanel>
                <TextBlock Text="Source:"/>
                <TextBlock Text="{Binding Path=Source}" />
                <TextBlock Text="Original Source:"/>
                <TextBlock Text="{Binding Path=OriginalSource}" />
            </StackPanel>  
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <ItemsPresenter Margin="5" />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
</ItemsControl>
2
Andy

J'ai eu un problème avec lequel je montrais une ItemsControl dans une grille et pour voir les barres de défilement, je devais donner à cette grille une hauteur de la taille d'une cellule *. 

Cependant, cela signifiait que la variable ItemsControl remplissait toujours la cellule même lorsqu'il y avait peu de valeurs. 

Je voulais que la ItemsControl soit seulement assez grande pour montrer ce qu’elle possédait, mais si elle contenait trop d’articles, je la voulais faire défiler. Dans les mots d'ordre, je voulais que cela fonctionne uniquement avec un moniteur de taille. 

Ce code dans l'événement Loaded a fonctionné pour moi:

Size x = new Size(double.PositiveInfinity, double.PositiveInfinity);
myItemscontrol.Measure(x);
0
Richard Fencel

Le défilement doit être le parent de l'enfant en train de redimensionner; placez donc le contrôle de redimensionnement (dans ce cas, le panneau de pile).

<ScrollViewer>
    <StackPanel>
         <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
         <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
         <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
         <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
         <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
    </StackPanel>

0
MikeT