这种行为的原因是
Viewbox
子对象被赋予无限的空间来测量其所需的大小。拉伸
TextBox
ES到无穷大
Width
没有什么意义,因为无论如何都无法呈现,所以会返回它们的默认大小。
您可以使用转换器来达到所需的效果。
public class ToWidthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double gridWidth = (double)value;
return gridWidth * 2/6;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
你可以把所有的东西连接起来添加这些资源。
<Viewbox.Resources>
<local:ToWidthConverter x:Key="ToWidthConverter"/>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Width"
Value="{Binding ActualWidth,
RelativeSource={RelativeSource AncestorType={x:Type Grid}},
Converter={StaticResource ToWidthConverter}}"/>
</Style>
</Viewbox.Resources>
更新
我很难理解无穷大的原始问题
网格宽度。
无限空间法常被用来确定
DesiredSize
A的
UIElement
. 简而言之,您为控件提供它可能需要的所有空间(没有约束),然后测量它以检索其所需的大小。
可视框
使用此方法测量其子项,但我们的
Grid
是动态的大小(否
Height
或
宽度
在代码中设置),因此
可视框
在网格子级下一级,查看它是否可以通过取组件的和来确定大小。
但是,当组件总数超过总可用大小时,您可能会遇到问题,如下所示。
我用标签替换了文本框
Foo
和
Bar
并将背景色设置为灰色。现在我们可以看到
酒吧
正在入侵
Body
领土,这显然不是我们要发生的事情。
同样,问题的根源来自
可视框
不知道如何将无穷大分成6等份(以映射到列宽
1*
,
2*
,
1**
,
2**
,所以我们需要做的就是用网格宽度恢复链接。在
ToWidthConverter
目的是绘制
文本框
’
宽度
到
网格
S
ColumnWidth
属于
2**
,所以我用
gridWidth * 2/6
. 现在
可视框
能够再次求解方程:每个
文本框
得到三分之一
gridwidth
,每个
Label
一半的那个(
1**
VS
2**
)
当然,当你把事情搞砸的时候,通过引入新的列,你必须注意保持组件和总的可用宽度同步。换句话说,这个方程需要是可解的。
输入math,所需大小(您尚未约束的控件的大小,我们示例中的标签)和转换后的大小(作为
gridWidth
,在我们的示例中,文本框)需要小于或等于可用大小(
网格宽度
在我们的例子中)。
我发现如果使用转换后的大小
文本框
让星星大小
列宽
S处理大多数其他事务。记住要保持在可用的总尺寸范围内。
增加灵活性的一种方法是
ConverterParameter
混合起来。
public class PercentageToWidthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double gridWidth = (double)value;
double percentage = ParsePercentage(parameter);
return gridWidth * percentage;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
private double ParsePercentage(object parameter)
{
// I chose to let it fail if parameter isn't in right format
string[] s = ((string)parameter).Split('/');
double percentage = Double.Parse(s[0]) / Double.Parse(s[1]);
return percentage;
}
}
一个划分
网格宽度
超过10股等额股份,并相应地将这些股份分配给各组成部分。
<Viewbox Stretch="Uniform">
<Viewbox.Resources>
<local:PercentageToWidthConverter x:Key="PercentageToWidthConverter"/>
</Viewbox.Resources>
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Label Content="Field A" Grid.Column="0" />
<TextBox Grid.Column="1"
Width="{Binding ActualWidth,
RelativeSource={RelativeSource AncestorType={x:Type Grid}},
Converter={StaticResource PercentageToWidthConverter},
ConverterParameter=2/10}" />
<Label Content="Field B" Grid.Column="2" />
<TextBox Grid.Column="3"
Width="{Binding ActualWidth,
RelativeSource={RelativeSource AncestorType={x:Type Grid}},
Converter={StaticResource PercentageToWidthConverter},
ConverterParameter=3/10}" />
<Button Content="Ok" Grid.Column="4"
Width="{Binding ActualWidth,
RelativeSource={RelativeSource AncestorType={x:Type Grid}},
Converter={StaticResource PercentageToWidthConverter},
ConverterParameter=1/10}" />
</Grid>
</Viewbox>
注意每个控件的共享,分组为2-2-2-3-1(ButtonWidth为1)。
最后,根据您所追求的可重用性,处理这一问题的其他一些方法:
-
在根上设置固定大小
网格
. 缺点:
-
每次更改组件时都需要进行微调(以实现
所需的水平/垂直/字体大小比率)
-
这个比例可能会在不同的主题、Windows版本…
-
添加一个
Behavior
. 在你链接的答案之一中完成
FontSize
post,但它的实现是将列宽映射到
网格宽度
。
-
根据@grx70的建议创建自定义面板。