2009-05-11 6 views
2

J'ai un projet qui utilise un DataGrid avec un modèle personnalisé afin que je puisse ajouter une ligne spéciale au bas des lignes de données. Je voudrais que cette rangée spéciale soit épinglée sous la dernière rangée mais pas dans le cadre du ScrollViewer, de sorte qu'elle reste épinglée sous la dernière rangée jusqu'à ce que le bas de la rangée spéciale atteigne le bas de la grille de données, alors je voudrais que le range la zone à la taille de l'espace entre et défile en conséquence, avec la ligne spéciale toujours visible. Jusqu'à présent, j'ai ma rangée spéciale dans le ScrollViewer avec le RowsPresenter. Le présentateur et la ligne spéciale se trouvent dans des rangées de taille automatique Grid dans le ScrollViewer, avec le ScrollViewer dans une ligne de grille en étoile pour que la barre de défilement apparaisse lorsqu'elle manque d'espace. Comment puis-je obtenir de cela, où les lignes et la rangée spéciale défilent ensemble vers où je veux être, où les rangées défilent, mais la rangée spéciale est épinglée en bas et toujours visible?Comment puis-je épingler un contrôle sous un autre dans Silverlight?

Bien que mon exemple utilise un DataGrid, je suis sûr que cela peut être simplifié jusqu'à un simple élément de défilement de hauteur variable, et un contrôle épinglé au-dessous. Jusqu'à présent, j'imagine que j'ai besoin d'un plutôt que d'un Grid pour héberger ma ligne spéciale ScrollViewer et mon compagnon, avec une certaine logique pour ajuster les hauteurs et les positions lorsque le ScrollViewer grandit (si je peux le détecter), mais je n'ai pas encore essayé . Y a-t-il un meilleur moyen ou le Canvas approche-t-il le meilleur disponible?

Répondre

1

J'ai été capable de résoudre ce problème en utilisant un Grid avec deux lignes de taille automatique; une ligne pour le DataGrid et une ligne pour ma rangée épinglée. Je surveille ensuite le dimensionnement du Grid et, lors du redimensionnement, cherche à voir si la valeur de ActualHeight de Grid est supérieure à la taille de l'écran à laquelle il est donné. Si c'est le cas, je change la ligne de DataGrid en taille d'étoile, ce qui entraîne la ligne épinglée apparaissant épinglé au bas du contrôle parent et le DataGrid affichant une barre de défilement pour ses lignes. Je change la ligne en auto-dimensionnement lorsque plus d'espace est disponible.

Cela fonctionnerait évidemment pour n'importe quel scénario où une rangée doit toujours être sur l'écran mais doit également être épinglé au fond d'une autre.

Le code épinglant ressemble à ceci:

RowDefinition row = this.mainGrid.RowDefinitions[0]; 
if (row.Height.GridUnitType == GridUnitType.Auto) 
{ 
    if (this.mainGrid.ActualHeight > this.ActualHeight) 
    { 
     row.Height = new GridLength(1, GridUnitType.Star); 
    } 
} 
else 
{ 
    if (this.dataGrid.DesiredSize.Height < row.ActualHeight) 
    { 
     row.Height = GridLength.Auto; 
    } 
} 
0

D'abord, créer une grille pour le contrôle principal et le contrôle épinglé:

<Grid Grid.Row="0" VerticalAlignment="Top"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" />    
     <RowDefinition Height="Auto" />    
    </Grid.RowDefinitions> 

    <!-- The main control, that is about to stretch. --> 
    <sdk:DataGrid Grid.Row="0" ItemsSource="{Binding YOUR_COLLECTION}" /> 

    <!-- The pinned control. --> 
    <TextBlock Grid.Row="1" Text="Hello World" /> 
</Grid> 

L'astuce est VerticalAlignment = "Top" - quand le contrôle principal est plus petit que la hauteur disponible, il se déplacera vers le haut de l'espace disponible et le contrôle épinglé apparaîtra en dessous.

Ensuite, mettez cette grille dans un récipient qui s'étend verticalement, par exemple dans une rangée d'une autre grille avec une hauteur étoile:

<Grid x:Name="LayoutRoot"> 
    <Grid.RowDefinitions> 
     <!-- RowDefition for the Grid with the main control and the pinned control. --> 
     <!-- If you want to have some other controls, --> 
     <!-- add other RowDefinitions and put these controls there. --> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 

    <!-- The internal Grid for the main control and the pinned control. --> 
    <Grid Grid.Row="0" VerticalAlignment="Top"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*" />    
      <RowDefinition Height="Auto" />    
     </Grid.RowDefinitions> 

     <sdk:DataGrid Grid.Row="0" ItemsSource="{Binding YOUR_COLLECTION}" /> 

     <TextBlock Grid.Row="1" Text="Hello World" /> 
    </Grid> 
</Grid> 

au lieu de la grille de racine que vous pouvez avoir tout autre récipient qui s'étend verticalement, l'important est qu'il essaie de remplir tout l'espace disponible pour cela.

Questions connexes