WPF 网格和 DataGrid 大小调整

发布于 2024-08-19 10:31:36 字数 1632 浏览 10 评论 0原文

我尝试使用的 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>

然后将此 UserControl 放置在我的 Window 中,作为一个 Grid,唯一一个带有 Height="*" 的网格。我对 DataGrid 的大小调整方式有疑问。

如果我将 UserControlVerticalAlignment 设置为 Window 中的 Stretch,则 PrimaryGrid获取 UserControl 的 1/2 高度,Border 内的两个高度均获取 1/4。无论每个网格有多少行,它们的大小都是这样的,导致 OtherGrid 的垂直空间太小,而其他网格在滚动视图内有非行空白。

如果我将 VerticalAlignment 设置为 Top,网格的大小似乎与它们的内容相当合适,除了在 UserControl< 的底部留下了一个莫名其妙的空白。 /代码>。我使用了 Snoop,UserControlRowDefinition 具有正确的 ActualHeight,但 UserControl 仅使用了它 - 80% 左右。

我真的不介意是否修复 Stretch 情况(How do I make the DataGrid not stretch more than its number of rows?) 或 Top< /code> case(如何使 UserControl 使用其可用的所有空间?)

The UserControl I'm trying to work with is essentially laid out like so:

<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="*". I'm having problems with the way the DataGrids are sized.

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

本王不退位尔等都是臣 2024-08-26 10:31:36

摘要:对 UserControl 使用 Stretch,但对 UserControl 内的行高使用 Auto(而不是 *) 。

解释:“自动”意味着< /a>:所需的空间(这是您想要的),而“*”表示:所有可用空间的比例份额(导致 1/2、1/4、1/4 分配)。

由于您希望 UserControl 使用所有可用空间,因此 Stretch 是正确的选项(这正是这个意思)。如果您希望该行占用剩余的可用空间,请将 UserControl 内的其中一个行高设置回“*”。

Summary: Use Stretch for the UserControl, but Auto (instead of *) for the row heights inside your UserControl.

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

Since you want the UserControl to use all available space, Stretch is the correct option (it means exactly that). Set one of the row heights inside the UserControl back to "*", if you want this row to take up the remaining available space.

毁我热情 2024-08-26 10:31:36

这是一个常见问题,您真正想要的是 2 种完全不同的布局行为:当有空间容纳所有三个时自动调整大小,* 当没有空间时调整大小。您可以尝试一些有限制的快速修复:

  • 自动调整大小(如前所述)
  • DockPanel,每个设置为 Dock=Top - 这将具有与 VerticalAlignment=Top 类似的效果,但最后一个 DataGrid(仅 1)将伸展以填充剩余空间。如果第一个或第二个占用的空间比现有空间多,那也很糟糕,因为它们会将其他空间推出。
  • 将 MinHeight/MaxHeight 与 DataGrid 上的其他 2 个更改之一结合起来设置,以防止它们失控。这会放弃一些自动布局的灵活性,以换取确保所有内容都显示出来。

除此之外,您还可以尝试更复杂的操作,例如创建自定义面板(或找到其他人已经制作的面板),或者创建一个 MultiValueConverter,它可以根据高度计算每个 DG 或行的适当高度(或 MinHeight、MaxHeight)设置。 UC 和每个 DG。

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

沫尐诺 2024-08-26 10:31:36

好吧,这就是我最终得到的结果。从布局的角度来看,它基本上满足了我的要求。后面的代码比我想要的多一点,但是哦,好吧。

在我的 DataContextChanged 事件处理程序中:

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

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
}

即使设置了 DataGrid 的 MaxHeight 后,情况仍然如此丑陋,所以我也必须在 RowDefinition 上设置最大高度。但这仍然不对,导致上面添加了 margin_height 。

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

在某些时候,我会在丑陋的最大高度代码中考虑我可选的可见行详细信息。

就 Top 与 Stretch 而言,由于其他原因,我最终将用户控件放在 ListView 中。现在一切尺寸都很好。

再次感谢您关注我的问题。

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:

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

//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. But that still wasn't right, causing the margin_height addition above.

<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. Everything sizes nicely now.

Thanks again for looking at my problem.

纵性 2024-08-26 10:31:36

只是想跟进这个问题。随着时间的推移,我上面提供的解决方案并没有达到用户的期望。我现在已经更改为这样的方案:

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

在我使用此习惯用法的另一个地方,我将 Resizer 设置为将 MaxHeight 绑定到 ScrollViewer 的 ActualHeight 以防止其失控。这种设计可能会与整体滚动条以及 DataGrid 中的滚动条有点混淆,但是有了良好的边框和边距,还不错。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文