简体   繁体   中英

XAML Divide Height amongst controls

I have a window split up by grids (left center right), where the center control I want to have multiple controls that will need to fill their heights as tall as possible while splitting it evenly amongst the other controls.

One way I was able to achieve this is through a grid like so:

<!-- Center -->
<Grid Grid.Row="0" Grid.Column="2" Height="Auto">
    <Grid.RowDefinitions>
         <RowDefinition Height="*" />
         <RowDefinition Height="*" />
         <RowDefinition Height="*" />

     </Grid.RowDefinitions>

     <WebBrowser Grid.Row="0" Name="browsc" />
     <WebBrowser Grid.Row="1" Name="browsa" />
     <WebBrowser Grid.Row="2" Name="browsb" />
</Grid>

This works, however I need to add and remove rows dynamically, where it's possible a row in the middle will need to be removed (causing the need to reorder the rows each control rests on which I can't imagine a simple solution for).

If there isn't a better way to split the controls than this, how would I add and remove rows via code (C#)?

If there's a better way to do it, how can I do this where all I have to worry about are adding and removing the controls themselves and not mess with row properties?

Thanks!

This is an example on how to add new RowDefinition to Grid programmatically and set control to a specific Grid Row :

//following line equal to XAML : <RowDefinition Height="*" />
var newrow = new RowDefinition {Height = new GridLength(1, GridUnitType.Star)};
//add new rowdefinition to grid
myGridName.RowDefinitions.Add(newrow);
//set webbrowser control to newly added row, or any row number you wish
Grid.SetRow(browsx, myGridName.RowDefinitions.Count-1);

You can access any RowDefinition from myGridName.RowDefinitions property to delete it later. But a better idea is to set RowDefinition's Height to zero instead of delete it. With that you don't have to rearrange other controls, moving control in row 3 to row 2 for example because the previous row 2 has been deleted.

This seems like a good case for UniformGrid :

<UniformGrid Grid.Row="0" Grid.Column="2" Columns="1">
    <WebBrowser Name="browsc" />
    <WebBrowser Name="browsa" />
    <WebBrowser Name="browsb" />
</UniformGrid>

UniformGrid ensures that all items have the same size, both width and height. In your case you only want to constrain height, but since there is only one column, all items must have the same width anyway, so this is okay.

Instead of setting up rows, we can just set Columns="1" on the UniformGrid and it will auto-arrange each item on a new row. If you add or remove items, or toggle their Visibility between Visible and Collapsed , all the sizes will be adjusted to fit the space.

Another possibility still using a grid is to bind the height to a converter that uses the visibility of the control it contains to decide on the layout.

Here's an example:

In the XAML file:

<Grid Grid.Row="0" Grid.Column="2" Height="Auto" xmlns:local="clr-namespace:WpfApplication2">
    <Grid.Resources>
        <local:RowHeightConverter x:Key="RowHeightConverter" />
    </Grid.Resources>
    <Grid.RowDefinitions>
        <RowDefinition Height="{Binding ElementName=browsc, Path=IsVisible, Converter={StaticResource RowHeightConverter}}" />
        <RowDefinition Height="{Binding ElementName=browsa, Path=IsVisible, Converter={StaticResource RowHeightConverter}}" />
        <RowDefinition Height="{Binding ElementName=browsb, Path=IsVisible, Converter={StaticResource RowHeightConverter}}" />
    </Grid.RowDefinitions>

    <WebBrowser Grid.Row="0" Name="browsc"></WebBrowser>
    <WebBrowser Grid.Row="1" Name="browsa" Visibility="Collapsed"></WebBrowser>
    <WebBrowser Grid.Row="2" Name="browsb"></WebBrowser>
</Grid>

You can also move the 'xmlns bit up to a top-level window or you may already have it.

In the code behind:

public class RowHeightConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var isVisible = value as bool?;
        if (isVisible.HasValue && isVisible.Value)
            return new GridLength(1, GridUnitType.Star);
        else
            return new GridLength(0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Once you've built the code once, you can change the 'Visibility' of the browsers in the XAML designer and see the changes reflected in the layout.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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