WPF/XAML将元素的宽度绑定到屏幕尺寸的一部分

4
我正在使用C#/WPF编写一个应用程序,想知道如何将网格列定义的宽度绑定到屏幕宽度的一部分。这个可行吗?基本上我想要这样的效果:
网格 = 2x2 第一行高度 = 屏幕高度的2/3 第二行高度 = 屏幕高度的1/3 第一行宽度 = 屏幕宽度的2/3 第二行宽度 = 屏幕宽度的1/3
我认为以下代码可以将整个宽度绑定到一个列定义中:
<ColumnDefinition Width="{Binding ElementName=Window1, Path=Width}"/>

但我不知道如何对通过数据绑定获取的值执行操作...这是否可能?我觉得这是应该能够编码到XAML中而不必在程序中实现的,但我对UI设计的经验很少:( 我想要类似于:

<ColumnDefinition Width="{Binding ElementName=Window1, Path=Width} * 2 / 3"/>

但那是无效的

我是否应该编写一个函数,以便在屏幕大小调整时重新布局UI元素?我觉得这很冗余...或者有没有一些简单的方法可以做到这一点,我不知道?欢迎任何意见!谢谢!

2个回答

5
听起来你只想使用星号大小:
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="2*"/>
        <RowDefinition Height="1*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*"/>
        <ColumnDefinition Width="1*"/>
    </Grid.ColumnDefinitions>

这将始终给第一行高度的2/3和第二行高度的1/3,同时给第一列宽度的2/3和第二列宽度的1/3。它将基于 Grid 的大小,但如果 Grid 是 Window 的唯一子项,则 Grid 的大小将与 Window 的大小相同。


0
我遇到一个情况,需要将一个控件的宽度绑定到另一个控件的高度的一部分上,但我认为没有一个方便的内置方式可以像这样分割绑定属性。最终,我编写了一个转换器,它会将绑定的值除以转换器参数来解决这个问题,而不是采用代码后台,我想分享一下,以防其他人也能节省一些时间。我在这里发布它,因为当我搜索是否有更清洁的方法时,这篇文章是第一个结果。

转换器类:

[ValueConversion(typeof(double), typeof(double))]
public class DoubleDivisionConverter : System.Windows.Data.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if(value == null) { return 0.0; }
        if(parameter == null) { return value; }

        double param;
        if(Double.TryParse(parameter.ToString(), out param))
        {
            if(param == 0) { return 0.0; }
            return (double)value / param;
        }
        else
        {
            throw new ArgumentException("Could not parse converter parameter as double.");
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if(value == null) { return 0.0; }
        if(parameter == null) { return value; }

        double param;
        if(Double.TryParse(parameter.ToString(), out param))
        {
            if(param == 0) { return 0.0; }
            return (double)value * param;
        }
        else
        {
            throw new ArgumentException("Could not parse converter parameter as double.");
        }
    }
}

XAML:(在UniformGrid Width属性上使用的转换器)

<Window.Resources>
    <converters:DoubleDivisionConverter x:Key="DoubleDivisionConverter"/>
</Window.Resources>

<Grid x:Name="sampleGrid">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.Resources>
        <Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="FontSize" Value="18"/>
            <Setter Property="FontWeight" Value="Bold"/>
        </Style>
    </Grid.Resources>

    <Border x:Name="rSample" Grid.Column="0" Grid.Row="0" Background="PaleVioletRed">
        <TextBlock>
            <TextBlock.Inlines>
                <Run Text="{Binding ElementName=rSample, Path=ActualWidth, StringFormat={}{0:N1}px, Mode=OneWay}"/><Run Text=", "/><Run Text="{Binding ElementName=rSample, Path=ActualHeight, StringFormat={}{0:N1}px, Mode=OneWay}"/>
            </TextBlock.Inlines>
        </TextBlock>
    </Border>

    <!-- Set the UniformGrids width to 1/3 the height of the parent grid using the converter -->
    <UniformGrid Grid.Column="1" Grid.Row="0" Columns="1"
    Width="{Binding ElementName=sampleGrid, Path=ActualHeight, Converter={StaticResource DoubleDivisionConverter}, ConverterParameter=3, Mode=OneWay}">
        <Border x:Name="gSample" Background="LightGreen">
            <TextBlock>
                <TextBlock.Inlines>
                    <Run Text="{Binding ElementName=gSample, Path=ActualWidth, StringFormat={}{0:N1}px, Mode=OneWay}"/><Run Text=", "/><Run Text="{Binding ElementName=gSample, Path=ActualHeight, StringFormat={}{0:N1}px, Mode=OneWay}"/>
                </TextBlock.Inlines>
            </TextBlock>
        </Border>
        <Border x:Name="ySample" Background="LightGoldenrodYellow">
            <TextBlock>
                <TextBlock.Inlines>
                    <Run Text="{Binding ElementName=ySample, Path=ActualWidth, StringFormat={}{0:N1}px, Mode=OneWay}"/><Run Text=", "/><Run Text="{Binding ElementName=ySample, Path=ActualHeight, StringFormat={}{0:N1}px, Mode=OneWay}"/>
                </TextBlock.Inlines>
            </TextBlock>
        </Border>
        <Border x:Name="bSample" Background="LightBlue">
            <TextBlock>
                <TextBlock.Inlines>
                    <Run Text="{Binding ElementName=bSample, Path=ActualWidth, StringFormat={}{0:N1}px, Mode=OneWay}"/><Run Text=", "/><Run Text="{Binding ElementName=bSample, Path=ActualHeight, StringFormat={}{0:N1}px, Mode=OneWay}"/>
                </TextBlock.Inlines>
            </TextBlock>
        </Border>
    </UniformGrid>
</Grid>

结果:

Result


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