我如何优先考虑WPF文本框包装自动调整大小?

时间:2011-08-01 22:09:14

标签: c# wpf textbox autosize

我有很多情况下我有自动调整大小的面板或网格,但如果它们包含带有TextBox的{​​{1}},TextWrapping="Wrap"会继续将面板/网格扩展为在它真正需要之前的很长时间,例如下图:

Textbox expanding the panel

我要做的是让TextBox在尝试向右扩展之前通过包装文本来填充其区域。该问题的简化示例是:

TextBox

我在Stack Overflow here上发现了一个类似的问题,但发布的最佳解决方案不允许<Grid> <Grid Background="Black" /> <Grid VerticalAlignment="Top" HorizontalAlignment="Left" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBox TextWrapping="Wrap" Height="120" MinWidth="200" /> </Grid> </Grid> 扩展。该解决方案类似于:

TextBox

除了使用已修改的行为扩展<Grid> <Grid Background="Black"> </Grid> <Grid VerticalAlignment="Top" HorizontalAlignment="Left" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> <Border BorderThickness="0" x:Name="border" Margin="0.5" /> <TextBox TextWrapping="Wrap" Height="120" MinWidth="200" Width="{Binding ActualWidth, ElementName=border}" /> </Grid> </Grid> 之外的任何其他想法?

3 个答案:

答案 0 :(得分:6)

有一个简单的技巧可以让它发挥作用。使用Canvas,然后将文本框的宽度绑定到画布的 actualwidth ,将画布的 height 绑定到 actualheight 的文本框。

<Canvas 
    x:Name="Canvas" 
    Height="{Binding ElementName=TextBlock, Path=ActualHeight}" 
    VerticalAlignment="Stretch" HorizontalAlignment="Stretch">

        <TextBlock
            x:Name="TextBlock"
            Width="{Binding ElementName=Canvas, Path=ActualWidth}"
            TextWrapping="WrapWithOverflow"
            Text="blah blah blah blah" />


</Canvas>

使用它的我们的制作应用程序的屏幕截图

enter image description here

并调整大小

enter image description here

技巧是Canvas继承父容器的宽度和子容器的高度。我考虑将模式包装在自定义控件中。

答案 1 :(得分:3)

虽然我不建议这样做,因为我认为这会给用户带来意想不到的行为,但这似乎达到了你的要求:

XAML:

<TextBox ... MinHeight="120" Width="200" SizeChanged="TextBox_SizeChanged" />

代码背后:

private void TextBox_SizeChanged(object sender, SizeChangedEventArgs e)
{
    try
    {
        if (e.PreviousSize == Size.Parse("0,0")) return;
        if (e.PreviousSize == e.NewSize) return;

        if (e.HeightChanged)
        {
            ((TextBox)sender).Width = e.PreviousSize.Width + 20;
        }
    }

    finally
    {
        e.Handled = true;
    }
}

要注意的一些事项,1)为了使其工作,您必须同时允许MinHeightWidth进行扩展,2)水平扩展20只是一个任意值我用于测试目的;你想要提出一种更可靠的计算变量扩展值的方法。

答案 2 :(得分:0)

我现在要解决的问题是上面提到的边界技巧,并解释得更好here。为了让TextBox自动填充Grid中的区域并在用户增大或缩小窗口时自行调整大小,占位符边框的边距必须更大 TextBox的边距。

此解决方案不会像最初需要的那样自动水平扩展,但它比扩展到正确问题的单行文本更好。

上图中带有边框技巧的面板示例xaml(文本框的边距为5):

<Grid>
    <!-- Diagram Window -->
    <Expander Header="{Binding Source={StaticResource labels}, Path=DiagramToolBoxHeader}" IsExpanded="True">
        <Grid MinWidth="200" MinHeight="200">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="Auto" ></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="10"></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="10"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Style="{StaticResource LabelHeader}" Content="{Binding Title}" />
            <Label Grid.Row="1" Grid.Column="1" Style="{StaticResource SolutionDiagramNameInput}" Content="{Binding SolutionDiagramNameLabel}" />
            <Label Grid.Row="2" Grid.Column="1" Style="{StaticResource DescriptionInput}" Content="{Binding DescriptionLabel}" />
            <TextBox Grid.Row="1" Grid.Column="2" Text="{Binding SolutionDiagramName, Mode=TwoWay}" />
            <Border Name="PlaceHolderBorder" Grid.Column="2" Margin="7"/>
            <TextBox Grid.Row="2" Grid.Column="2" Text="{Binding Description, Mode=TwoWay}" VerticalScrollBarVisibility="Auto"
                     TextAlignment="Left" TextWrapping="Wrap" Width="{Binding ElementName=PlaceHolderBorder, Path=ActualWidth}" />
            <StackPanel Orientation="Horizontal" Grid.Row="3" Grid.Column="2" Margin="5">
                <Button Command="{Binding UpdateCommand}" Content="{Binding UpdateButtonLabel}"></Button>
                <Button Command="{Binding ResetCommand}" Content="{Binding ResetButtonLabel}"></Button>
                <Button Command="{Binding DefaultsCommand}" Content="{Binding DefaultsButtonLabel}"></Button>
                <Button Command="{Binding CloseConfirmCommand}" Content="{Binding CloseButtonLabel}"></Button>
            </StackPanel>
        </Grid>
    </Expander>
</Grid>