Как установить максимальную ширину столбца сетки в зависимости от размера окна или экрана в XAML - PullRequest
7 голосов
/ 17 сентября 2008

У меня есть сетка из 3 столбцов в окне с GridSplitter в первом столбце. Я хочу установить MaxWidth первого столбца на треть родительского окна или страницы Width (или ActualWidth), и я бы предпочел сделать это в XAML, если это возможно.

Это пример XAML для игры в XamlPad (или аналогичный), который показывает, что я делаю.

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

Как видите, ширина правого столбца привязана к ширине первого столбца, поэтому, когда вы перемещаете левый столбец с помощью разделителя, правый столбец делает то же самое :) Если вы сдвинете левый столбец вправо, в конечном итоге он переместится на половину страницы / окна и перейдет к правой стороне окна, оттолкнув столбцы 2 и 3.

Я хочу предотвратить это, установив MaxWidth столбца 1 на треть ширины окна (или что-то в этом роде). Я могу сделать это в коде довольно легко, но как это сделать в «XAML Only»?

РЕДАКТИРОВАТЬ: Дэвид Шмитт предложил использовать SharedSizeGroup вместо привязки, что является отличным предложением. Мой пример кода будет выглядеть так:

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

Ответы [ 2 ]

7 голосов
/ 01 октября 2008

Я думаю, что подход только к XAML несколько сложен, но вот способ сделать это.

<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>
0 голосов
/ 17 сентября 2008

Лень на самом деле писать сам, но вы должны быть в состоянии использовать математический конвертер и привязываться к ширине родительского окна (либо по имени, либо с помощью поиска предка RelativeSource).

//I know I borrowed this from someone, sorry I forgot to add a comment from whom
public class ScaledValueConverter : IValueConverter
{
  public Object Convert(Object value, Type targetType, Object parameter, System.Globalization.CultureInfo culture)
  {
     Double scalingFactor = 0;
     if (parameter != null)
     {
        Double.TryParse((String)(parameter), out scalingFactor);
     }

     if (scalingFactor == 0.0d)
     {
        return Double.NaN;
     }

     return (Double)value * scalingFactor;
  }

  public Object ConvertBack(Object value, Type targetType, Object parameter, System.Globalization.CultureInfo culture)
  {
     throw new Exception("The method or operation is not implemented.");
  }
}
...