WPF: Setting the Width (and Height) as a Percentage Value
Solution 1
The way to stretch it to the same size as the parent container is to use the attribute:
<Textbox HorizontalAlignment="Stretch" ...
That will make the Textbox element stretch horizontally and fill all the parent space horizontally (actually it depends on the parent panel you're using but should work for most cases).
Percentages can only be used with grid cell values so another option is to create a grid and put your textbox in one of the cells with the appropriate percentage.
Solution 2
You can put the textboxes inside a grid to do percentage values on the rows or columns of the grid and let the textboxes auto-fill to their parent cells (as they will by default). Example:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" />
<TextBox Grid.Column="1" />
</Grid>
This will make #1 2/5 of the width, and #2 3/5.
Solution 3
Typically, you'd use a built-in layout control appropriate for your scenario (e.g. use a grid as a parent if you want scaling relative to the parent). If you want to do it with an arbitrary parent element, you can create a ValueConverter do it, but it probably won't be quite as clean as you'd like. However, if you absolutely need it, you could do something like this:
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();
}
}
Which can be used like this, to get a child textbox 10% of the width of its parent canvas:
<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>
Solution 4
For anybody who is getting an error like : '2*' string cannot be converted to 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>
Solution 5
IValueConverter implementation can be used. Converter class which takes inheritance from IValueConverter takes some parameters like value
(percentage) and parameter
(parent's width) and returns desired width value. In XAML file, component's width is set with the desired value:
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>
Related videos on Youtube
Andreas Grech
+++++[>+++++[>++++<-]<-]>>+++.--..++++++. Contactable at $(echo qernfterpu#tznvy?pbz | tr ?a-z# .n-za-m@)
Updated on December 11, 2020Comments
-
Andreas Grech over 3 years
Say I want a
TextBlock
to have itsWidth
equal to it's Parent container'sWidth
(ie, stretch from side to side) or a percentage of it's Parent ContainerWidth
, how can I accomplish this inXAML
without specifying absolute values?I want to do this so that if the Parent Container container is later on expanded (its'
Width
increased), its' Child Elements will also be expanded automatically. (basically, like in HTML and CSS)-
Jesper Fyhr Knudsen about 15 yearsHave a look at this answer.
-
Shimmy Weitzhandler over 14 yearsUse cwap's answer and include the tb in a grid setting it's alignment to stretch.
-
-
Andreas Grech about 15 yearsI already tried that, but I'm getting this error: '2*' string cannot be converted to Length.'
-
Shimmy Weitzhandler over 14 yearsYour answer helped me a lot, thanks! I tried to figure out what the * does for years, you explained it so short and good.
-
EightyOne Unite over 13 years:-) ,... the * is called "star"
-
Pratik Deoghare over 13 yearsActually, *(Asterisk) is little star ;) etymonline.com/index.php?term=asterisk
-
Jeremy about 13 yearsThis is really cool, how can I do it in code (set the width of the textbox)?
-
Denys Wessels over 10 yearsMy mom says I'm a star
-
Darren about 10 yearsThis does not work, even if the TextBox is in a Grid. The width can be set to a Double, Qualified Double (A double value followed by px, in, cm or pt) or Auto. See msdn.microsoft.com/en-GB/library/…
-
cwap about 10 yearsYes.. This is actually a very poor reply, but based on all the upvotes, I suppose it helped someone (was a long time ago), which is why I haven't deleted it.
-
Ben almost 10 yearsWhy not
<RowDefinition Height="auto" />
? -
Flat Eric over 9 yearsYou should consider adding
CultureInfo.InvariantCulture
to the double conversion because theparameter
is regarded asstring
and in cultures with differentdecimal separator
it will not work as expected. -
Yama over 9 years"auto" takes only as much space as the control needs
-
Mafii about 8 yearsThank you so much, this should be the top answer.
-
Knut Valen about 8 yearsThis is definitely the best answer.
-
Norman over 6 yearsNow that we're at the end of '17, 2* 3* is absolutely valid. Even the Visual Studio GUI provides fields to specify such values.
-
prw56 about 4 yearsJust wanted to offer another confirmation that this does work with newer xaml versions