开发者

WPF Layout question... How to scroll and auto-size content?

All,

I am开发者_JS百科 coming from a primarily ASP.NET background, but have experience with Windows forms as well. I am trying to learn how to layout my WPF app. I have the following code:

<Grid>

    <Grid.RowDefinitions>
        <RowDefinition Height="40" />
        <RowDefinition Height="*" />
        <RowDefinition Height="40" />
    </Grid.RowDefinitions>

    <Button Grid.Row="0" Width="80" Content="Do Something"
            HorizontalAlignment="Right" Margin="5" />

    <DataGrid Grid.Row="1" Name="dgGrid" AutoGenerateColumns="True" />

    <Button Grid.Row="2" Width="80" Content="Do Something Else"
            HorizontalAlignment="Right" Margin="5" />

</Grid>

When the DataGrid is short, the top and bottom rows are where I'd expect... at the top and bottom of the window with the center row taking up the rest of the visible space. When the DataGrid is too long, however, the bottom row is forced off-screen. Is there a way to have the DataGrid scroll when it is too long to fit in the visible space?

Setting the center row's height to a fixed value causes the DataGrid to scroll, but I want the height to be dynamic as the window is resized.

Any help is appreciated...

Thanks, Lou


You can solve this by using dock panel. In dock panel, add the first button and dock it at top. Then add the second button and dock it at bottom. Now add the datagrid. Make sure DockPanel LastChildFill is true. This will give you the result you want. I did not test the code, so you may need little tuning but it should work.

<DockPanel LastChildFill="True">
<Button DockPanel.Dock="Top" Width="80" Content="Do Something"
        HorizontalAlignment="Right" Margin="5" />

<Button DockPanel.Dock="Bottom" Width="80" Content="Do Something Else"
        HorizontalAlignment="Right" Margin="5" />


Try a ScrollViewer:

<ScrollViewer Grid.Row="1">
    <DataGrid Name="dgGrid" AutoGenerateColumns="True" />
</ScrollViewer>


I'm not 100% sure I'm tracking your question but if I'm correct the following are a few suggestions:

  • Your button disappears when the form is resized because the form reduces below the viewable area. You can restrict this by adding a "MinHeight" to the Window such as: `MinHeight="240". This will prevent the user from shrinking the form below the threshold and having controls "disappear".
  • Set a minimum height for the rows so they are always viewable and don't disappear (the above will take care of this to come extent as long as it's greater than the height of the fixed rows [80 + middle row height] Suggestion:

    <Grid.RowDefinitions>
        <RowDefinition Height="40" MinHeight="40" />
        <RowDefinition Height="*" MinHeight="120" />
        <RowDefinition Height="40" MinHeight="40" />
    </Grid.RowDefinitions>
    
  • The data grid should have scrollbars automatically, unless the property's been altered, but you might double check that VerticalScrollBarVisibility="Auto"


(Sorry, can't leave a comment yet...)

My issue is not minimum height, but rather max height. I don't want the DataGrid to expand beyond the visible area, but it does. If I explicitly set a height on the center row, the DataGrid's scrolling kicks in as expected, but if I use "*" as the height, the DataGrid expands past the viewable area. So if the "=" represent the window, here is a representation of what I am experiencing...

===================================
= ROW 0 - Button                  =
= _______________________________ =
= ROW 1 - DataGrid                =
=     --------------------------- =
=     --------------------------- =
=     --------------------------- =
=     --------------------------- =
===================================
      ---------------------------
      ---------------------------
      ---------------------------
      ---------------------------
  _______________________________
  ROW 2 - Button

ScrollViewer did not work either.

Thanks!


Lou,

I too am struggling with this problem. There is a solution, but it doesn't seem to work so well on Windows XP. The trick is to reserve space for your DataGrid by creating a placeholder row that is empty. Move your DataGrid outside of the layout grid and set the margins as shown below.

<Grid SizeChanged="Grid_SizeChanged">
    <Grid.RowDefinitions>
        <RowDefinition Height="40" />
        <RowDefinition Name="DetailGridRow" Height="*" />
        <RowDefinition Height="40" />
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Width="80" Content="Do Something" Margin="5" />
    <Button Grid.Row="2" Width="80" Content="Do Something Else" Margin="5" />
</Grid>
<DataGrid Margin="0,40,0,40" Name="dgGrid" AutoGenerateColumns="True" />

Now place this SizeChanged handler is your code behind class.

/// <summary>
/// In order to prevent the datagrid from growing vertically the size is set to an empty
/// Grid row's size.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
    Grid layoutGrid = sender as Grid;
    double marginWidth = (layoutGrid.Margin.Left + layoutGrid.Margin.Right);
    double marginHeight = (layoutGrid.Margin.Top + layoutGrid.Margin.Bottom);
    double minHeight = dgGrid.MinHeight;

    if (e.HeightChanged)
        dgGrid.Height = DetailGridRow.ActualHeight > minHeight ?
        DetailGridRow.ActualHeight - marginHeight : minHeight - marginHeight;
    if (e.WidthChanged)
        dgGrid.Width = layoutGrid.ActualWidth - marginWidth;

    e.Handled = false;
}

As I mentioned earlier, this technique has problems on Windows XP. The problem that I run into is that the column widths are all messed up resulting in a grid that is unusable unless you find the "magic" column and double-click it's column divider, which restores all the column widths to their correct size. I'm still working out the solution to that.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜