Как я могу расставить приоритеты обтекания текстовых полей WPF над автоматическими размерами? - PullRequest
10 голосов
/ 02 августа 2011

У меня есть несколько ситуаций, когда у меня есть панели или сетки, которые изменяют размер автоматически, но если они содержат TextBox с TextWrapping="Wrap", TextBox продолжает расширять панель / сетку вправо задолго до того, как она действительнонеобходимо, например, на изображении ниже:

Textbox expanding the panel

Я хочу сделать так, чтобы TextBox заполнил свою область путем переноса текста, прежде чем он попытается расшириться доправо.Упрощенный пример проблемы:

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

Какие-нибудь идеи, кроме расширения TextBox с измененным поведением?

Ответы [ 3 ]

7 голосов
/ 27 марта 2015

Есть простой трюк, чтобы заставить его работать. Используйте Canvas и затем привяжите width текстового поля к фактической ширине холста и height холста к фактической высоте текстового поля.

<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 наследует ширину от родительского контейнера и высоту от его дочернего элемента. Я подумываю об упаковке шаблона в пользовательский элемент управления.

3 голосов
/ 02 августа 2011

Хотя я бы не рекомендовал делать это, так как считаю, что это приводит к неожиданному поведению пользователя, похоже, это позволяет достичь того, о чем вы просите:

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) для того, чтобы это работало, вы должны либо MinHeight, либо Width для расширения и 2)горизонтальное расширение 20 - это произвольное значение, которое я использовал для тестирования;Вы захотите придумать более надежный способ вычисления значения расширения переменной.

0 голосов
/ 02 августа 2011

Решение, с которым я сейчас работаю, - это уловка границы, упомянутая выше, и объясненная лучше здесь .Чтобы 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>
...