wpf 如何根据 XAML 中的窗口或屏幕大小设置网格列 MaxWidth
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/82323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Set Grid Column MaxWidth depending on Window or Screen Size in XAML
提问by Johan Danforth
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.
我在一个窗口中有一个 3 列网格,第一列上有一个 GridSplitter。我想将第一列的 MaxWidth 设置为父窗口或页面Width
(或ActualWidth
)的三分之一,如果可能,我更愿意在 XAML 中执行此操作。
This is some sample XAML to play with in XamlPad (or similar) which shows what I'm doing.
这是在 XamlPad(或类似的)中使用的一些示例 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" >
<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.
如您所见,右列的宽度与第一列的宽度绑定,因此当您使用拆分器滑动左列时,右列的作用相同:) 如果您将左列向右滑动,最终它将滑过页面/窗口的一半并移到窗口的右侧,推开第 2 列和第 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"?
我想通过将第 1 列的 MaxWidth 设置为窗口宽度的三分之一(或类似的东西)来防止这种情况发生。我可以很容易地在后面的代码中做到这一点,但如何在“仅 XAML”中做到这一点?
EDIT:David Schmitt suggested to use SharedSizeGroup instead of binding, which is an excellent suggestion. My sample code would look like this then:
编辑:David Schmitt 建议使用 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>
回答by Christopher Bennage
I think the XAML-only approach is somewhat circuitous, but here is a way to do it.
我认为仅使用 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>
回答by Thomas
Too lazy to actually write it up myself, but you should be able to use a mathematical converter and bind to your parent windows width (either by name, or with a RelativeSource ancestor search).
懒得自己写出来,但您应该能够使用数学转换器并绑定到您的父窗口宽度(按名称或使用 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.");
}
}