如何根据XAML中的窗口或者屏幕大小设置网格列的最大宽度
时间:2020-03-05 18:58:39 来源:igfitidea点击:
我在窗口中有一个3列网格,在第一列中有一个GridSplitter。我想将第一列的最大宽度设置为父窗口或者页面"宽度"(或者"实际宽度")的三分之一,如果可能的话,我希望在XAML中进行此设置。
这是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>
如我们所见,右列的宽度绑定到第一列的宽度,因此,当我们使用拆分器滑动左列时,右列的作用相同:)
如果将左列向右滑动,最终它将滑过页面/窗口的一半,并滑到窗口的右侧,推开第2列和第3列。
我想通过将列1的MaxWidth设置为窗口宽度的三分之一(或者类似的值)来防止这种情况。我可以很容易地在后面的代码中执行此操作,但是如何在"仅XAML"中执行此操作?
编辑: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>
解决方案
回答
懒得自己亲自编写它,但是我们应该能够使用数学转换器并将其绑定到父窗口宽度(通过名称或者使用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的方法有些circuit回,但这是一种实现方法。
<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>