162

假设我希望 aTextBlock等于Width它的 Parent 容器Width(即,从一侧延伸到另一侧)或它的 Parent Container 的百分比,Width我如何在XAML不指定绝对值的情况下完成此操作?

我想这样做,以便如果父容器容器稍后扩展(它的'Width增加),它的'子元素也将自动扩展。(基本上,就像在 HTML 和 CSS 中一样)

4

7 回答 7

244

您可以将文本框放在网格内以在网格的行或列上执行百分比值,并让文本框自动填充到其父单元格(默认情况下)。例子:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*" />
        <ColumnDefinition Width="3*" />
    </Grid.ColumnDefinitions>

    <TextBox Grid.Column="0" />
    <TextBox Grid.Column="1" />
</Grid>

这将使#1 2/5 的宽度和#2 3/5。

于 2009-04-04T16:04:34.460 回答
99

将其拉伸到与父容器相同大小的方法是使用属性:

 <Textbox HorizontalAlignment="Stretch" ...

这将使 Textbox 元素水平拉伸并水平填充所有父空间(实际上它取决于您使用的父面板,但应该适用于大多数情况)。

百分比只能与网格单元格值一起使用,因此另一种选择是创建一个网格并将您的文本框放在具有适当百分比的单元格中。

于 2009-04-04T16:24:10.640 回答
64

通常,您会使用适合您的场景的内置布局控件(例如,如果您想要相对于父级缩放,则使用网格作为父级)。如果您想使用任意父元素执行此操作,您可以创建一个 ValueConverter 执行此操作,但它可能不会像您想要的那样干净。但是,如果您绝对需要它,您可以执行以下操作:

public class PercentageConverter : IValueConverter
{
    public object Convert(object value, 
        Type targetType, 
        object parameter, 
        System.Globalization.CultureInfo culture)
    {
        return System.Convert.ToDouble(value) * 
               System.Convert.ToDouble(parameter);
    }

    public object ConvertBack(object value, 
        Type targetType, 
        object parameter, 
        System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

可以像这样使用它,以获取其父画布宽度的 10% 的子文本框:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <local:PercentageConverter x:Key="PercentageConverter"/>
    </Window.Resources>
    <Canvas x:Name="canvas">
        <TextBlock Text="Hello"
                   Background="Red" 
                   Width="{Binding 
                       Converter={StaticResource PercentageConverter}, 
                       ElementName=canvas, 
                       Path=ActualWidth, 
                       ConverterParameter=0.1}"/>
    </Canvas>
</Window>
于 2009-04-04T16:35:35.277 回答
39

对于任何遇到以下错误的人:'2*' 字符串不能转换为长度。

<Grid >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*" /><!--This will make any control in this column of grid take 2/5 of total width-->
        <ColumnDefinition Width="3*" /><!--This will make any control in this column of grid take 3/5 of total width-->
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition MinHeight="30" />
    </Grid.RowDefinitions>

    <TextBlock Grid.Column="0" Grid.Row="0">Your text block a:</TextBlock>
    <TextBlock Grid.Column="1" Grid.Row="0">Your text block b:</TextBlock>
</Grid>
于 2012-09-17T16:48:13.243 回答
7

可以使用 IValueConverter 实现。从 IValueConverter 继承的转换器类接受一些参数,如value(百分比)和parameter(父宽度)并返回所需的宽度值。在 XAML 文件中,组件的宽度设置为所需的值:

public class SizePercentageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (parameter == null)
            return 0.7 * value.ToDouble();

        string[] split = parameter.ToString().Split('.');
        double parameterDouble = split[0].ToDouble() + split[1].ToDouble() / (Math.Pow(10, split[1].Length));
        return value.ToDouble() * parameterDouble;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // Don't need to implement this
        return null;
    }
}

XAML:

<UserControl.Resources>
    <m:SizePercentageConverter x:Key="PercentageConverter" />
</UserControl.Resources>

<ScrollViewer VerticalScrollBarVisibility="Auto"
          HorizontalScrollBarVisibility="Disabled"
          Width="{Binding Converter={StaticResource PercentageConverter}, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualWidth}"
          Height="{Binding Converter={StaticResource PercentageConverter}, ConverterParameter=0.6, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualHeight}">
....
</ScrollViewer>
于 2016-08-31T02:52:23.913 回答
4

我知道这不是 XAML,但我对文本框的 SizeChanged 事件做了同样的事情:

private void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
   TextBlock textBlock = sender as TextBlock;
   FrameworkElement element = textBlock.Parent as FrameworkElement;
   textBlock.Margin = new Thickness(0, 0, (element.ActualWidth / 100) * 20, 0);
}

文本框的大小似乎是其父级的 80%(右侧边距为 20%),并在需要时拉伸。

于 2009-04-05T12:20:00.063 回答
4

我使用两种方法来确定相对大小。我有一个Relative带有三个附加属性的类To,如果我希望一个元素成为可视树中任何位置的元素的相对大小并且感觉不如转换器方法那么难懂 - 尽管使用对你有用的东西,你'很高兴。WidthPercentHeightPercent

另一种方法则更为狡猾。在里面添加一个ViewBox你想要相对大小的地方,然后在里面,Grid在宽度 100 处添加一个。然后如果你在TextBlock里面添加一个宽度为 10 的,它显然是 100 的 10%。

将根据给定的任何空间进行ViewBox缩放Grid,因此如果它是页面上唯一的东西,那么Grid将被缩放到整个宽度并且有效地TextBlock缩放到页面的 10%。

如果你没有设置高度,Grid那么它会缩小以适应它的内容,所以它都是相对大小的。您必须确保内容不会太高,即开始改变空间的纵横比,ViewBox否则它也会开始缩放高度。您可能可以使用Stretchof解决此问题UniformToFill

于 2013-07-30T10:39:11.260 回答