Expand last grid row to fill window in wpf application - c#

I have the following Grid setup in a WPF application.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="220" />
<RowDefinition Height="40" />
<RowDefinition Height="80" />
<RowDefinition Height="180*" />
</Grid.RowDefinitions>
<!-- some content -->
</Grid>
What I want is for the final row to take up as much height as available in its parent. But it does not seem to honor my '*' command in the final row definition.
Please note that I want all other row heights to be fixed..
Is this possible? If so how? Any help or pointers are appreciated..

place height="*" in last row.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="220" />
<RowDefinition Height="40" />
<RowDefinition Height="80" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

What you have written should be fine (though as #Bolu commented, the 180* could be replaced with * in this case). If the content in the last row is not expanding to fill the available size, I would suspect one of the following:
The Grid may be nested somewhere below a layout panel that does not arrange its children to fill all available vertical space. For example, is one of the Grid panel's ancestors a StackPanel? A good way to test whether this is the culprit is to comment out the entire Grid and replace it with a Border with an easily distinguishable background (e.g., Magenta) and see if it occupies the entire area you expect the Grid to fill.
There may not actually be any content in the last row. Did you set the correct Grid.Row value correctly?
You may be overriding the layout behavior of the last row's content. Are you setting the content's VerticalAlignment to anything other than Stretch?

Remove the Height property from the last Row:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="220" />
<RowDefinition Height="40" />
<RowDefinition Height="80" />
<RowDefinition/>
</Grid.RowDefinitions>
<!-- some content -->
</Grid>

Related

Resolution Independent WPF Application

I'm developing a Database system that needs to be resolution independent, some use screens that are still running at 1024 x 768, some use screens that are at 1920 x 1080 and others use everything in between.
I haven't done much work with WPF before so I'm sort of just starting out and attempting to get my head around height, widths and alignments.
What I have at the moment is one main window that holds an grid in which at the top there is a row for a label and some navigation buttons, as well as the time and the username of the person logged in. I then have a second row below that that holds a frame which I load pages into for the main navigation of the program.
In the pages I mainly use the grid layout, and occasionally the stack panel. One of the biggest problems I have come across is an issue like this;
In low resolutions this is common, where as in a higher resolution the buttons look fine;
This is the XAML code for the buttons within their parent grid;
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Content="HR" Margin="10" Click="RunHrSystem" FontSize="18.667" />
<Button Content="Companies" Margin="10" Click="RunCompSystem" FontSize="18.667" Grid.Row="1" />
<Button Content="People" Margin="10" Click="RunPeopleSystem" FontSize="18.667" Grid.Row="2" />
<Button Content="IT Management" Margin="10" Click="RunITManagementSystem" FontSize="18.667" Grid.Row="3"/>
<Button Content="Sales" Margin="10" FontSize="18.667" Grid.Row="4" />
<Button Content="Buying" Margin="10" FontSize="18.667" Grid.Row="5" />
<Button Content="Estimating" Margin="10" FontSize="18.667" Grid.Row="6"/>
<Button Content="Design" Margin="10" FontSize="18.667" Grid.Row="7"/>
</Grid>
Is there anything obvious I am doing wrong here that is preventing the buttons from resizing according to a lower resolution? As I say I get this throughout my program when using buttons, as well as the rectangle shape and in some situations labels, where the bottom of the label will be cut off too.
Currently, you are declaring RowDefinitions to use *, this tells the row to use the height as a percentage of the available space. Therefore, if your resolution changes, your row heights will change.
Instead, you want the RowDefinition to be the height of the content. In this case, when the resolution changes, the row heights will not change.
<RowDefinition Height="Auto"/>
It'd be a good idea to put the grid in a ScrollViewer, just in case the grid becomes larger than the screen.
<ScrollViewer>
<Grid>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
...
In your particular example, I would instead use a StackPanel.
<ScrollViewer>
<StackPanel>
<Button ...
I guess it's a bad practice to hide existing buttons in a non-visible area. The user should scroll for accessing bottom buttons. If you need to support the low-resolution monitor, an app should adjust to the current resolution.
I guess the best way is decreasing the margin, set * for RowDefinitions and limit grid height to prevent huge stretching.

How to make WPF WrapPanel height automatically grow (double) when wrap to two lines occurs

I have a grid with two rows like
<Grid.RowDefinitions>
<RowDefinition Height="44" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<WrapPanel Grid.Row="0" HorizontalAlignment="Stretch" Orientation="Horizontal">
//...
</WrapPanel>
In the first row I am placing a WrapPanel with horizontal orientation. The elements within the WrapPanel are approx 40 heigth so it looks cool when there is only one line. However when the items wraps to two lines (say because the user decreases the width of the column with GridSplitter) then the WrapPanel correctly breaks into two line, but the second line is not shown, because the fixed 44 row height.
How can I achieve that the first row should be 44 or 88 according the WrapPanel's one line or two line layout?
Thanks in advance
It's a shame I did not figured out... "Auto" is the answer. Auto is never worked for me so maybe that's why it was not popped up in my mind first....
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<WrapPanel Grid.Row="0" HorizontalAlignment="Stretch" Orientation="Horizontal">

How to color only one row of a grid?

I'm creating small browser as user control. I want to colour only one row because i'm moving address bar to bottom of grid. I tried to change Background in RowDefinitions but there isn't such property in XAML.
So how to do that?
That is correct, you are not supposed to set a background in RowDefinitions.
You could for example use a Grid to do that.
Here is a small example:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0"
Background="AliceBlue" />
</Grid>

understanding WPF Layout

I got a ListView (wrapped in a ScrollViewer), which resizes itself if the elements inseretd exceed the visible area until the parents Max Height is reached.
The ListView is embedded the following way.
<Window ... SizeToContent="Height">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="MyScrollViewer" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListView Name="MyListView"
ItemsSource="{Binding Path=RetrievalStringResults, Mode=OneWay}"
IsSynchronizedWithCurrentItem="True" />
</ScrollViewer>
<DockPanel Grid.Row="0" Grid.Column="1">
...
</DockPanel>
<Expander Grid.Row="1" Grid.ColumnSpan="2">
<DockPanel Height="150" HorizontalAlignment="Stretch">
<TextBox DockPanel.Dock="Top" />
</DockPanel>
</Expander>
<DockPanel Grid.Row="2" Grid.ColumnSpan="2">
... some buttons
</DockPanel>
</Grid>
</Window>
I used SizeToContent because I got a text box on the bottom wrapped in an Expander, which shall expanded on demand, and actually therefore my main window needs to resize. This actually works fine.
The problem is though the ListView's Height isn't the max height on start-up wherefore I got that "auto-resize" effect.
How can I set the ListView's hight to the max of the parents height to avoid this effect?
Another, more general issue. I think avoiding static layout parameters (static values for hight/width) is nice, but I got the feeling I'm loosing some control over my UI controls.
I recognized, resizeing my main window manually in height, it "jumps" by the 150 height of the DockPanel wrapped by the Expander on the bottom, anyway to avoid this?
What is the best pratice in dynamic UI Layout? I explored DockPanel beeing more dynamically in sizing to the surounding contorls than a StackPanel. But I guess thats not everything.
I think your issue is with your Grid definitions
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
...
</Grid>
This means that the top row is going to be twice the size of rows 2 and 3, so the top row will only take up 50% of your space while your bottom two rows each take up 25% space.
If you want the top row to take up all available space, make sure it is the only * size row, and set the other rows to Auto so they will take up whatever space they need.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
...
</Grid>

What is better in WPF for UI layout, using one Grid, or nested Grids

I am making a UI in WPF, I have a bunch of functional areas and I use a Grid to organize it.
Now the Grid that I want is not uniform, as in, some functional area will span multiple cells in the Grid. I was wondering what the best practise is in solving this. Should I create one grid and then for each functional area set it to span multiple cells, or should I split it up into multiple nested Grids.
In this image, the leftmost panel (panels separated by the gray bar) is what I want. The middle panel shows one grid where the blue lines are overlapped by a functional area. The rightmost panel shows how I could do it with nested grids. You can see the green grid has one horizontal split. In the bottom cell is the yellow Grid with a vertical split. In side the left cell is the red Grid with again a horizontal split.
Grids http://www.freeimagehosting.net/uploads/08f2711bae.jpg
I was just wondering what is best practise, the middle or the right panel.
UPDATE: Just for clarification, a more 'code oriented' example:
The Middle panel
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Menu Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" />
<uc:Info Grid.Row="1" Grid.Column="0" />
<uc:Control Grid.Row="2" Grid.Column="0" />
<uc:Simulation Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" />
</Grid>
The Right panel:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Menu Grid.Row="0"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<uc:Info Grid.Row="0" />
<uc:Control Grid.Row="1" />
</Grid>
<uc:Simulation Grid.Column="1" />
</Grid>
</Grid>
Update: I have to admit that now that I wrote out the code for both approaches, the "span" solution looks a lot better.
I would personally go with your middle layout using a single grid with column and row spans to structure the overall layout of the UI, then put a panel in each of those sections to contain the actual controls (and possible further detailed layout).
I would recommend to create one master grid divided into functional areas, then create separate grids/stackpanels/etc in these areas.
You may not know the requirements for each functional area, so you can arrange their elements freely and switch bettween layouts. When you put everything in one grid with span columns and/or rows - you would get a "hard to manage" layout.
I am afraid I am unable to distinguish your solutions with the color in the different grids and sub-grids.
What I can advise is to create a UserControl for each functional area, then have a grid to arrange these areas.
Each UserControl is then free to create its own layout (with another grid, or a simpler StackPanel, or whatever) and is responsible to display a data subset/handle user events in its own area.
The outer grid is then an arbiter for things that involve more than one area (e.g. event forwarding between areas).
Frankly i would go for a dockpanel or like that for top level composition, and grids for low level

Categories