简体   繁体   English

WPF Grid和DataGrid大小调整

[英]WPF Grid and DataGrid sizing

The UserControl I'm trying to work with is essentially laid out like so: 我试图使用的UserControl基本上是这样布局的:

<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>

This UserControl is then placed in my Window as the last member of a Grid , the only one with Height="*" . 然后将此UserControl作为Grid的最后一个成员放在我的Window中,唯一一个Height="*" I'm having problems with the way the DataGrid s are sized. 我对DataGrid的大小调整方式有疑问。

If I set VerticalAlignment of the UserControl to Stretch in the Window , then PrimaryGrid gets 1/2 height of the UserControl , and each of the two inside the Border get 1/4. 如果我在Window中将UserControl VerticalAlignment设置为Stretch ,则PrimaryGrid将获得UserControl 1/2高度,并且Border内的两个中的每一个都获得1/4。 They are sized like this regardless of the number of rows each have, leaving OtherGrid with too little vertical space and the others with non-row whitespace inside the scrollview. 无论每个行的行数是多少,它们的大小都是这样的,使得OtherGrid垂直空间太小而OtherGrid的其他行具有非行空格。

If I set VerticalAlignment to Top , the grids seem to size pretty well to their contents, except there is an inexplicable whitespace being left at the bottom of the UserControl . 如果我将VerticalAlignment设置为Top ,则网格的大小似乎与其内容相当,除非在UserControl的底部留下一个莫名其妙的空白。 I used Snoop and the RowDefinition for the UserControl has the proper ActualHeight , but the UserControl only uses a portion of it - 80% or so. 我使用Snoop和UserControlRowDefinition具有正确的ActualHeight ,但UserControl只使用它的一部分 - RowDefinition 80%左右。

I don't really mind whether I fix the Stretch case (How do I make the DataGrid not stretch larger than its number of rows?) or the Top case (How do I make the UserControl use all the space it has available to it?) 我真的不介意我是否修复Stretch情况(如何使DataGrid不会拉伸大于其行数?)或Top case(如何让UserControl使用它可用的所有空间? )

Summary : Use Stretch for the UserControl, but Auto (instead of * ) for the row heights inside your UserControl. 简介 :对UserControl使用Stretch ,但对UserControl中的行高使用Auto (而不是* )。

Explanation : "Auto" means : as much space as needed (which is what you want), whereas "*" means: a proportional share of all available space (resulting in the 1/2, 1/4, 1/4-distribution). 说明 :“自动” 表示 :尽可能多的空间(这是您想要的),而“*”表示:所有可用空间的比例份额(产生1 / 2,1 / 4,1 / 4分布) )。

Since you want the UserControl to use all available space, Stretch is the correct option (it means exactly that). 由于您希望UserControl使用所有可用空间,因此Stretch是正确的选项(这意味着)。 Set one of the row heights inside the UserControl back to "*", if you want this row to take up the remaining available space. 如果希望此行占用剩余的可用空间,请将UserControl中的一个行高设置为“*”。

This is a common problem where what you really want is 2 completely different layout behaviors: Auto sizing when there's room for all three, * sizing when there isn't. 这是一个常见的问题,你真正想要的是2种完全不同的布局行为:当有三个空间时自动调整大小,*没有时调整大小。 Some quick fixes you can try out with limitations: 您可以通过限制尝试一些快速修复:

  • Auto sizing (as already mentioned) 自动调整大小(如前所述)
  • DockPanel with each set to Dock=Top - this will have a similar effect to VerticalAlignment=Top but the last DataGrid (only 1) will stretch out to fill the remaining space. DockPanel,每个设置为Dock = Top - 这将对VerticalAlignment = Top产生类似的效果,但最后一个DataGrid(仅1)将拉伸以填充剩余空间。 Also bad if the first or second take up more space than exists because they'll push the others out. 如果第一个或第二个占用的空间比存在的多,那也很糟糕因为他们会把其他人推出去。
  • Set MinHeight/MaxHeight in combination with one of the other 2 changes on your DataGrids to keep them from getting out of control. 将MinHeight / MaxHeight与DataGrids中的其他2个更改之一结合使用,以防止它们失控。 This gives up some of the auto-layout flexibility in exchange for making sure everything shows up. 这样可以放弃一些自动布局的灵活性,以确保一切都显示出来。

Beyond those you can try something more complex like creating a custom Panel (or find one that someone else made already), or creating a MultiValueConverter that can calculate appropriate Height (or MinHeight, MaxHeight) settings for each DG or Row based on the height of the UC and each of the DGs. 除此之外,您可以尝试更复杂的内容,例如创建自定义面板(或找到其他人已经制作的面板),或者创建一个MultiValueConverter,可以根据高度为每个DG或行计算适当的高度(或MinHeight,MaxHeight)设置。 UC和每个DG。

Well, here's what I ended up with. 好吧,这就是我最终的结果。 It does what I want from a layout point of view, mostly. 它主要是从布局的角度来做我想要的。 A bit more code behind than I'd like, but oh well. 比我想要的更多的代码,但哦,好吧。

In my DataContextChanged event handler: 在我的DataContextChanged事件处理程序中:

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

PropertyObserver is from http://joshsmithonwpf.wordpress.com/2009/07/11/one-way-to-avoid-messy-propertychanged-event-handling/ PropertyObserver来自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
}

Even after setting the DataGrid's MaxHeight, things were still ugly, so I had to set the max height on the RowDefinition's too. 即使在设置DataGrid的MaxHeight后,事情仍然很难看,所以我不得不在RowDefinition上设置最大高度。 But that still wasn't right, causing the margin_height addition above. 但这仍然是不对的,导致margin_height添加到上面。

<RowDefinition Height="*" MaxHeight="{Binding ElementName=PrimaryGrid, Path=MaxHeight}"/>

At some point, I'll take into account my optionally visible row details in my ugly max height code. 在某些时候,我会在丑陋的最大高度代码中考虑我可选择的可见行详细信息。

As far as Top vs Stretch, I ended up for other reasons having the usercontrol in a ListView. 至于Top vs Stretch,我最终还是出于其他原因而在ListView中使用了usercontrol。 Everything sizes nicely now. 现在一切都很好。

Thanks again for looking at my problem. 再次感谢您查看我的问题。

Just wanted to follow up on this problem. 只是想跟进这个问题。 Over time, the solution I provided above just did not meet users expectations. 随着时间的推移,我上面提供的解决方案不符合用户的期望。 I've now changed to a scheme like this: 我现在改为这样的计划:

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

In another place where I've used this idiom, I've set the Resizer to have a MaxHeight bound to the ScrollViewer's ActualHeight to keep it from going out of control. 在我使用这个习语的另一个地方,我设置了Resizer,将MaxHeight绑定到ScrollViewer的ActualHeight,以防止它失去控制。 This design can be a little confusing with the overall scrollbar, plus scrollbars in the DataGrid, but with good borders and margins, it's not too bad. 这个设计可能会让整个滚动条与DataGrid中的滚动条有点混淆,但是边框和边距都很好,也不算太糟糕。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM