自动但已拉伸的WPF网格列宽度

时间:2019-12-13 09:08:12

标签: wpf

在我的应用程序中,我的窗口底部最多包含4个显示一些信息的文本。我不知道这些文本的内容,直到运行时为止,我也不知道是零还是最多4。永远不会超过4。

enter image description here

问题在于您在图片中看到的是第三个文本溢出。现在,这是因为此刻的实现是item控件中的统一网格:

<ItemsControl Grid.Row="2" Height="20" ItemsSource="{Binding VersionInfoItems}">
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type ess:VersionInformation}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="viGroup"/>
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal" Margin="3 0 5 0" HorizontalAlignment="Center">
                    <TextBlock Text="{Binding Key}"/>
                    <TextBlock Margin="0 0 4 0"><Run Text=":"/></TextBlock>
                    <TextBlock Text="{Binding Value}"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Rows="1" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

因此,我尝试使用网格将所有列定义都设置为“自动”来创建测试,但这只会使它们全部堆叠在一起:

enter image description here

我希望他们这样做:

enter image description here

是否可以配置网格或统一网格来实现此目的(或者我应该使用其他控件),还是必须在后面的代码中完成此操作,并以某种方式分析哪些区域溢出,然后将宽度校正为容纳文字?

我尝试对内容的宽度进行拉伸,但这没有效果。我还找到了一篇文章,内容是关于重写统一网格列定义的,但是由于我仅在运行时知道它们的内容和数量,因此不适用。

解决方案(基于Mikes的回答):

迈克的建议使我走上了正确的轨道,我使它行之有效,因此它可以处理我可能会收到的任意数量的文本:

enter image description here

enter image description here

我所做的是我添加了两个转换器,这些转换器返回Double.NaN的自动值或新的GridLength(1,GridUnitType.Star);对于星形列。然后,我从集合切换到设置的特定对象,然后将这些对象绑定到列定义和文本块:

<Grid Grid.Row="2">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="{Binding Vi1, Converter={StaticResource StarConverter}}"/>
        <ColumnDefinition Width="{Binding Vi1, Converter={StaticResource AutoConverter}}"/>
        <ColumnDefinition Width="{Binding Vi2, Converter={StaticResource StarConverter}}"/>
        <ColumnDefinition Width="{Binding Vi2, Converter={StaticResource AutoConverter}}"/>
        <ColumnDefinition Width="{Binding Vi3, Converter={StaticResource StarConverter}}"/>
        <ColumnDefinition Width="{Binding Vi3, Converter={StaticResource AutoConverter}}"/>
        <ColumnDefinition Width="{Binding Vi4, Converter={StaticResource StarConverter}}"/>
        <ColumnDefinition Width="{Binding Vi4, Converter={StaticResource AutoConverter}}"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <StackPanel Orientation="Horizontal" Margin="3 0 5 0" HorizontalAlignment="Center" Grid.Column="1">
        <TextBlock Text="{Binding Vi1.Key}"/>
        <TextBlock Margin="0 0 4 0"><Run Text=":"/></TextBlock>
        <TextBlock Text="{Binding Vi1.Value}"/>
    </StackPanel>
    <StackPanel Orientation="Horizontal" Margin="3 0 5 0" HorizontalAlignment="Center" Grid.Column="3">
        <TextBlock Text="{Binding Vi2.Key}"/>
        <TextBlock Margin="0 0 4 0"><Run Text=":"/></TextBlock>
        <TextBlock Text="{Binding Vi2.Value}"/>
    </StackPanel>
    <StackPanel Orientation="Horizontal" Margin="3 0 5 0" HorizontalAlignment="Center" Grid.Column="5">
        <TextBlock Text="{Binding Vi3.Key}"/>
        <TextBlock Margin="0 0 4 0"><Run Text=":"/></TextBlock>
        <TextBlock Text="{Binding Vi3.Value}"/>
    </StackPanel>
    <StackPanel Orientation="Horizontal" Margin="3 0 5 0" HorizontalAlignment="Center" Grid.Column="7">
        <TextBlock Text="{Binding Vi4.Key}"/>
        <TextBlock Margin="0 0 4 0"><Run Text=":"/></TextBlock>
        <TextBlock Text="{Binding Vi4.Value}"/>
    </StackPanel>
</Grid>

因此,如果设置了我的Vi对象,则对应的列定义将获得Auto或Star宽度。如果未设置,则两者都为0。以下是很好的转换器:

//Star converter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if(value != null)
        return new GridLength(1,GridUnitType.Star);
    return 0;
}

//Auto converter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value != null)
        return Double.NaN;
    return 0;
}

1 个答案:

答案 0 :(得分:2)

我不确定100%是否是您要的内容,但是我想您希望标签之间的间距均匀。我想到一个快速而肮脏的技巧,需要在标签之间添加空列(宽度为 star ),例如:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="1" Text="Text1: longer text" HorizontalAlignment="Center" />
    <TextBlock Grid.Column="3" Text="Text2" HorizontalAlignment="Center" />
    <TextBlock Grid.Column="5" Text="Very very extremly long text that gets clipped, or not" HorizontalAlignment="Center" />
    <TextBlock Grid.Column="7"  Text="Text3" HorizontalAlignment="Center" />
</Grid>

此代码为您提供以下结果(取决于标签中的文本长度):

enter image description here enter image description here

让我知道这是否可以解决您的问题。