WPF:将宽度(和高度)设置为百分比值


149

说我想要一个TextBlock有它Width等于它的父容器的Width(也就是说,从一边到另一边拉伸)或它的父容器的百分比Width,我怎么能在做到这一点XAML,而无需指定绝对值?

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



使用cwap的答案并将tb包括在其对齐以拉伸的网格设置中。
Shimmy Weitzhandler,2010年

Answers:


90

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

 <Textbox HorizontalAlignment="Stretch" ...

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

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


221

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

<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。


7
我已经尝试过了,但是出现了这个错误:“ 2 *”字符串无法转换为“长度”。
Andreas Grech

6
实际上,*(星号)是小星星;)etymonline.com/index.php?term=asterisk
Pratik Deoghare 2010年

73
我妈妈说我是明星
Denys Wessels 2014年

7
即使TextBox位于网格中,这也不起作用。宽度可以设置为Double,Qualified Double(双精度值,后跟px,in,cm或pt的double值)或自动。请参阅msdn.microsoft.com/zh-CN/library/…–
Darren

2
是的。这实际上是一个很差的答复,但是基于所有的投票,我想它帮助了某人(很久以前),这就是为什么我没有删除它。
cwap

58

通常,您将使用适合您的方案的内置布局控件(例如,如果要相对于父级缩放,请使用网格作为父级)。如果要使用任意父元素来执行此操作,可以创建一个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>

这真的很酷,如何在代码中进行设置(设置文本框的宽度)?
杰里米

9
您应该考虑添加CultureInfo.InvariantCulture双重转换,因为在不同的文化中,“与” parameter被视为string和,decimal separator将无法按预期工作。
Flat Eric

33

对于任何遇到错误的人,例如:'2 *'字符串都不能转换为Length。

<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>

为什么不<RowDefinition Height="auto" />呢?
2014年

2
“自动”仅占用控件所需的空间
2015年

非常感谢,这应该是最佳答案。
马菲

这绝对是最好的答案。
Knut Valen

7

可以使用IValueConverter实现。从IValueConverter继承的Converter类采用一些参数,例如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>

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%),并在需要时延伸。


4

我使用两种方法进行相对大小调整。我有一类叫做Relative有三个附加属性ToWidthPercent并且HeightPercent如果我想要一个元素是在视觉树元素的任何地方的相对大小是有用的,比转换器的做法感觉少哈克-尽管使用你的作品,你很高兴。

另一种方法更狡猾。在ViewBox其中要添加相对大小的位置添加一个,然后在其中添加Grid宽度为100的值。然后,如果在其中添加TextBlock宽度为10的值,则显然是100的10%。

ViewBox会的规模Grid根据任何空间,它已被赋予,所以如果其页面上的唯一的事情,那么Grid将被缩小了全宽和有效的,你TextBlock缩放页面的10%。

如果您未在上设置高度,Grid则它会缩小以适合其内容,因此它们的尺寸都相对较大。您必须确保内容不会太高,即开始更改给定空间的宽高比,ViewBox否则将开始缩放高度。您可以使用来解决此Stretch问题UniformToFill

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.