2010-01-21 7 views
1

Le UserControl Je suis en train de travailler avec est essentiellement aménagé comme ceci:WPF Grid et DataGrid dimensionnement

<Grid> 
    <Grid.RowDefinitions> 
     <Row Height="*"/> 
     <Row Height="*"/> 
    </Grid.RowDefinitions> 
    <wpftoolkit:DataGrid x:Name="PrimaryGrid"/> <!-- ~10 rows --> 
    <Border> 
     <Grid> 
     <Grid.RowDefinitions> 
      <Row Height="*"/> 
      <Row Height="*"/> 
     </Grid.RowDefinitions> 
     <wpftoolkit:DataGrid x:Name="SecondaryGrid"/> <!-- ~2 rows --> 
     <wpftoolkit:DataGrid x:Name="OtherGrid"/> <!-- ~50 rows --> 
     </Grid> 
    </Border> 
</Grid> 

Cette UserControl est ensuite placé dans mon Window comme le dernier membre d'un Grid, le seul avec Height="*". J'ai des problèmes avec la taille des DataGrid s.

Si je mets VerticalAlignment du UserControl-Stretch dans le Window, puis PrimaryGrid obtient 1/2 hauteur du UserControl, et chacun des deux à l'intérieur du Border obtenir 1/4. Ils sont dimensionnés comme ceci quel que soit le nombre de lignes, laissant OtherGrid avec trop peu d'espace vertical et les autres avec des espaces non-lignes dans le scrollview.

Si je mets VerticalAlignment-Top, les grilles semblent assez bien la taille de leur contenu, sauf qu'il est un des espaces inexplicable étant laissé au fond du UserControl. J'ai utilisé Snoop et le RowDefinition pour le UserControl a le bon ActualHeight, mais le UserControl en utilise seulement une partie - environ 80%.

Cela ne me dérange pas vraiment si je fixe le cas Stretch (Comment puis-je le DataGrid pas étirer plus grand que le nombre de lignes?) Ou le cas Top (Comment puis-je faire l'UserControl utiliser tout l'espace qu'il a ? dont il dispose)

Répondre

0

Eh bien, voici ce que j'ai fini avec. Il fait ce que je veux du point de vue de la mise en page, surtout. Un peu plus de code derrière que je ne le voudrais, mais bon.

Dans mon gestionnaire d'événements DataContextChanged:

//for each grid 
_reportObserver = new PropertyObserver<ItemCollection>(PrimaryGrid.Items) 
    .RegisterHandler(c => c.Count, c => UpdateMaxHeight(PrimaryGrid)); 
UpdateMaxHeight(PrimaryGrid); 

PropertyObserver est de http://joshsmithonwpf.wordpress.com/2009/07/11/one-way-to-avoid-messy-propertychanged-event-handling/

//Lots of ugly hard-coding  
private void UpdateMaxHeight(DataGrid grid) 
{ 
    double header_height = grid.ColumnHeaderHeight; 
    if (double.IsNaN(header_height)) 
     header_height = 22; 
    double margin_height = grid.Margin.Bottom + grid.Margin.Top; 
    grid.MaxHeight = header_height + margin_height + grid.Items.Count * (grid.RowHeight+2); 

    UpdateLayout(); //this is key for changes to number of items at runtime 
} 

Même une fois les choses étaient encore laid MaxHeight du DataGrid,, donc je devais régler la hauteur max sur la RowDefinition est aussi. Mais ce n'était toujours pas correct, provoquant l'ajout de margin_height ci-dessus. À un certain point, je prendrai en compte mes détails de rangée facultativement visibles dans mon code de hauteur max laid.

En ce qui concerne Top vs Stretch, je me suis retrouvé pour d'autres raisons ayant la commande usercontrol dans un ListView. Tout va bien maintenant.

Merci encore d'avoir regardé mon problème.

3

Résumé: Utilisez Stretch pour le UserControl, mais Auto (au lieu de *) pour les hauteurs de ligne à l'intérieur de votre UserControl.

Explication: « Auto » means: autant d'espace que nécessaire (ce qui est ce que vous voulez), alors que « * » signifie: une part proportionnelle de l'espace disponible (résultant en 1/2, 1/4 , 1/4-distribution). Comme vous voulez que UserControl utilise tout l'espace disponible, Stretch est l'option correcte (cela signifie exactement cela). Définissez un des hauteurs de ligne à l'intérieur du UserControl sur "*" si vous souhaitez que cette ligne prenne l'espace disponible restant.

+0

Je vais tenter le coup, mais la dernière fois que j'ai essayé Auto, OtherGrid étendu au bas de la fenêtre, sans barre de défilement. – Thomas

+0

Oui, tout auto est définitivement mauvais. Création des deux grilles Auto, * fonctionne un peu, jusqu'à ce que la taille de la fenêtre soit réduite. Ensuite, PrimaryGrid ne rétrécit pas et la bordure disparaît progressivement. Je pourrais peut-être leur donner une maxheight liée à une proportion de la hauteur réelle. Mais cela semble tellement inutile. Je pense que je veux lier MaxHeight du DataGrid à son ScrollableHeight, mais cela ne semble pas fonctionner. – Thomas

+0

Comme alternative: Qu'en est-il de l'utilisation de Auto et de mettre l'ensemble UserControl dans un 'ScrollViewer'? De cette façon, chaque DataGrid devrait obtenir l'espace dont il a besoin, et une barre de défilement (globale) peut être utilisée pour faire défiler. – Heinzi

1

C'est un problème courant où ce que vous voulez vraiment, c'est 2 comportements de mise en page complètement différents: Dimensionnement automatique quand il y a de la place pour les trois, * dimensionnement quand il n'y en a pas. Quelques solutions rapides que vous pouvez essayer avec des limites:

  • dimensionnement automatique (comme déjà mentionné)
  • DockPanel avec chaque jeu Dock = Top - cela aura un effet similaire à VerticalAlignment = Top mais la dernière DataGrid (seulement 1) s'étendra pour remplir l'espace restant. Aussi mauvais si le premier ou le second occupe plus d'espace qu'il n'y en a parce qu'ils vont repousser les autres.
  • Définissez MinHeight/MaxHeight en combinaison avec l'un des 2 autres changements sur vos DataGrids pour les empêcher de devenir hors de contrôle. Cela donne une partie de la flexibilité de mise en page automatique en échange de s'assurer que tout se présente.

Au-delà de ceux que vous pouvez essayer quelque chose de plus complexe comme la création d'un panneau personnalisé (ou en trouver un que quelqu'un d'autre a déjà), ou la création d'un MultiValueConverter qui permet de calculer la hauteur appropriée (ou MinHeight, MaxHeight) les paramètres de chaque DG ou Ligne basée sur la hauteur de l'UC et de chacune des DG.

+0

Merci beaucoup pour les idées. Voté – Thomas

0

Je voulais juste faire un suivi sur ce problème. Au fil du temps, la solution que j'ai fournie ci-dessus n'a tout simplement pas répondu aux attentes des utilisateurs. Je l'ai changé à un régime comme celui-ci:

<ScrollViewer VerticalScrollBarVisibility="Auto"> 
    <Grid> 
     <!-- row definitions --> 
     <KentBoogart's Resizer ResizeDirection="South"> 
     <DataGrid/> 
     </kb:Resizer> 
     <kb:Resizer ResizeDirection="South"> 
     <DataGrid/> 
     </kb:Resizer> 
    </Grid> 
</ScrollViewer> 

Dans un autre endroit où je l'ai utilisé cet idiome, je me suis fixé l'Resizer d'avoir un MaxHeight lié au ActualHeight du ScrollViewer pour l'empêcher de sortir de contrôle. Cette conception peut être un peu déroutante avec la barre de défilement globale, plus les barres de défilement dans le DataGrid, mais avec de bonnes frontières et de bonnes marges, ce n'est pas si mal.