Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Set Grid Column MaxWidth depending on Window or Screen Size in XAML

I have a 3 column grid in a window with a GridSplitter on the first column. I want to set the MaxWidth of the first column to a third of the parent Window or Page Width (or ActualWidth) and I would prefer to do this in XAML if possible.

This is some sample XAML to play with in XamlPad (or similar) which shows what I'm doing.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="Column1" Width="200"/>
            <ColumnDefinition x:Name="Column2" MinWidth="50" />
            <ColumnDefinition x:Name="Column3" Width="{ Binding ElementName=Column1, Path=Width }"/>
            </Grid.ColumnDefinitions>

        <Label Grid.Column="0" Background="Green" />
        <GridSplitter Grid.Column="0" Width="5" />
        <Label Grid.Column="1" Background="Yellow" />
        <Label Grid.Column="2" Background="Red" />
    </Grid>
</Page>

As you can see, the right column width is bound to the width of the first column, so when you slide the left column using the splitter, the right column does the same :) If you slide the left column to the right, eventually it will slide over half the page/window and over to the right side of the window, pushing away column 2 and 3.

I want to prevent this by setting the MaxWidth of column 1 to a third of the window width (or something like that). I can do this in code behind quite easily, but how to do it in "XAML Only"?

EDIT: David Schmitt suggested to use SharedSizeGroup instead of binding, which is an excellent suggestion. My sample code would look like this then:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
        <Grid IsSharedSizeScope="True">
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="Column1" SharedSizeGroup="ColWidth" Width="40"/>
                <ColumnDefinition x:Name="Column2" MinWidth="50" Width="*" />
                <ColumnDefinition x:Name="Column3" SharedSizeGroup="ColWidth"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0" Background="Green" />
            <GridSplitter Grid.Column="0" Width="5" />
            <Label Grid.Column="1" Background="Yellow" />
            <Label Grid.Column="2" Background="Red" />
        </Grid>
</Page>
like image 282
Johan Danforth Avatar asked Sep 17 '08 11:09

Johan Danforth


1 Answers

I think the XAML-only approach is somewhat circuitous, but here is a way to do it.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:sys="clr-namespace:System;assembly=mscorlib"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

    <!-- This contains our real grid, and a reference grid for binding the layout-->
    <Grid x:Name="Container">

      <!-- hidden because it's behind the grid below -->
      <Grid x:Name="LayoutReference">
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <!-- We need the border, because the column doesn't have an ActualWidth -->
        <Border x:Name="ReferenceBorder" 
                Background="Black" />
        <Border Background="White" Grid.Column="1" />
        <Border Background="Black" Grid.Column="2" />
      </Grid>

      <!-- I made this transparent, so we can see the reference -->
      <Grid Opacity="0.9">
          <Grid.ColumnDefinitions>
              <ColumnDefinition x:Name="Column1" 
                                MaxWidth="{Binding ElementName=ReferenceBorder,Path=ActualWidth}"/>
              <ColumnDefinition x:Name="Column2" 
                                MinWidth="50"  />
              <ColumnDefinition x:Name="Column3" 
                                Width="{ Binding ElementName=Column1, Path=Width }"/>
              </Grid.ColumnDefinitions>

          <Label Grid.Column="0" Background="Green"/>
          <GridSplitter Grid.Column="0" Width="5" />
          <Label Grid.Column="1" Background="Yellow" />
          <Label Grid.Column="2" Background="Red" />
      </Grid>
    </Grid>

</Page>
like image 96
Christopher Bennage Avatar answered Oct 13 '22 22:10

Christopher Bennage