Reputation: 1386
I want to bind a control's Width to the parent's Width, but to a certain scale. Is there a way to do something like this:
<Rectangle Name="rectangle1" Width="{Binding ActualWidth*0.3, ElementName=thumbnailCanvas, UpdateSourceTrigger=PropertyChanged}" Height="{Binding ActualHeight, ElementName=thumbnailCanvas, UpdateSourceTrigger=PropertyChanged}"/>
Upvotes: 9
Views: 33231
Reputation: 109
You can download a sample from https://github.com/omeraziz/NoTextOverflowWPF. It looks like a hack but it works!
<Window Title="NoTextOverflow"
x:Class="NoTextOverflow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="Auto" Height="Auto"
ResizeMode="CanResize" SizeToContent="WidthAndHeight">
<!--
There is no fixed width in any of the UI elements including window, Label, TextBlock, TextBox etc.
Window's SizeToContent grows and shrinks with the contents.
-->
<Grid Margin="10" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label VerticalAlignment="Center" Content="Type Here:" />
<TextBox x:Name="LongText"
Grid.Column="1" Grid.ColumnSpan="2"
Width="{Binding ElementName=WidthRestrictorGrid, Path=ActualWidth, Mode=OneWay}"
MinWidth="100"
Margin="5" HorizontalAlignment="Left" VerticalAlignment="Center"
Text="Type here a long message and resize this window" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" />
<!--
This grid is used to calculate width of middle two columns.
Remove this and its references to see the effect without this grid.
Since this is not parent of TextBox and TextBlock so it must have a Name to bind with its Actualwidth
-->
<Grid x:Name="WidthRestrictorGrid"
Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2"
Margin="10,1" HorizontalAlignment="Stretch" />
<TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"
Width="{Binding ElementName=WidthRestrictorGrid, Path=ActualWidth, Mode=OneWay}"
MinWidth="50"
Margin="5" HorizontalAlignment="Left" VerticalAlignment="Top"
Background="LightGray"
Text="{Binding ElementName=LongText, Path=Text}"
TextWrapping="Wrap" />
<Button Grid.Row="2" Grid.Column="3"
Margin="5" HorizontalAlignment="Right" VerticalAlignment="Bottom"
Content="Dummy" />
</Grid>
Upvotes: 0
Reputation: 31
Perhaps you can add a scale transform like this:
<Rectangle Name="rectangle1" Width="{Binding ActualWidth, ElementName=thumbnailCanvas, UpdateSourceTrigger=PropertyChanged}" Height="{Binding ActualHeight, ElementName=thumbnailCanvas, UpdateSourceTrigger=PropertyChanged}">
<Rectangle.RenderTransform>
<ScaleTransform ScaleX="0.3" ></ScaleTransform>
</Rectangle.RenderTransform>
</Rectangle>
Upvotes: 3
Reputation: 1170
Sure, but you will need to use a converter. Something like this one:
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
namespace WpfTestBench.Converters
{
public class PercentageConverter : MarkupExtension, IValueConverter
{
private static PercentageConverter _instance;
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return System.Convert.ToDouble(value) * System.Convert.ToDouble(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
public override object ProvideValue(IServiceProvider serviceProvider)
{
return _instance ?? (_instance = new PercentageConverter());
}
}
}
And your XAML will look like:
<Window x:Class="WpfTestBench.ScaleSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:WpfTestBench.Converters"
Title="Scale sample" Height="300" Width="300">
<Grid Name="ParentGrid">
<Rectangle
Width="{Binding Path=ActualWidth, ElementName=ParentGrid, Converter={converters:PercentageConverter}, ConverterParameter='0.5'}"
Stroke="Black" StrokeThickness="2" />
</Grid>
</Window>
Upvotes: 25
Reputation: 61
I'd recommend simply doing this in XAML using a grid columns and the * width type:
<Window x:Class="NameSpace.WindowName"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0"></Grid><!--This item take up 1/3 of window width-->
<Grid Grid.Column="1"></Grid> <!--This item take up remaining 2/3 of window width-->
</Grid>
</Window>
You can change the ratio of how much the columns take up by changing the numbers before the * in the column widths. Here it's setup as 1 and 2, so the grid will be split in 3 (sum of all * widths), with 1/3 of width to first column and 2/3 to second column.
Upvotes: 6