У меня есть сетка из 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»?
Обновлено: Дэвид Шмитт предложил использовать 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>





Слишком ленив, чтобы написать это самому, но у вас должна быть возможность использовать математический преобразователь и привязать к ширине родительских окон (либо по имени, либо с помощью поиска предков 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.");
}
}
Я думаю, что подход, основанный только на 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>
Я попробовал xaml выше в XamlPad, и он вёл себя как-то странно, но я понимаю вашу точку зрения! Спасибо.
Используйте SharedSizeGroup вместо привязки к ширине другого столбца!