WPF绑定Width到Parent.Width*0.3

9
我想将一个控件的宽度绑定到其父容器的宽度,但需要按照一定比例进行缩放。是否有类似以下代码可以实现此功能的方法:
<Rectangle  Name="rectangle1" Width="{Binding ActualWidth*0.3, ElementName=thumbnailCanvas, UpdateSourceTrigger=PropertyChanged}" Height="{Binding ActualHeight, ElementName=thumbnailCanvas, UpdateSourceTrigger=PropertyChanged}"/>

1
为什么不直接使用适当大小的列的网格呢? - Clemens
4个回答

24

当然可以,但您需要使用转换器。例如这个:

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());
        }
    }
}

你的XAML将如下所示:

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

2
请注意,“使用ToDouble(String)方法等同于将值传递给Double.Parse(String)方法,该值使用当前线程文化的格式约定进行解释”。 - Somedust
我想将这样的东西添加到我的应用程序中,但是当我尝试实现它(包括直接复制)时,我会收到错误信息:“[名称"PercentageConverter"在命名空间"clr-namespace:WpfTestBench.Converters"中不存在]”,即使按照您编写的方式完全复制到我的应用程序中,它也肯定存在。 - ARidder101

6
我建议您在XAML中使用网格列和*宽度类型来完成此操作:
<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>

您可以通过更改列宽中 * 前面的数字来改变列占用比例。在这里,它设置为 1 和 2,因此网格将被分成三份(所有 * 宽度的总和),其中第一列的宽度为 1/3,第二列的宽度为 2/3。


2
也许您可以添加一个类似于这样的比例变换:
<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>

我想这应该是答案。 - Benjol

0
您可以从https://github.com/omeraziz/NoTextOverflowWPF下载一个示例。它看起来像是一个hack,但它确实有效!
<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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接