简体   繁体   中英

Making a WPF TextBlock be only grow and not shrink?

In my app I set the Text of the TextBlock named tbkStatus many times.

How can I make the TextBlock be just grow auto to fit the text but not shrink when the text changed?

The StatusText changes every few seconds, There are statuses with long text and short text. I want my TextBlock to fit itself to the size of the longest text that was, and even when there is a short text the TextBlock should not shrink

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="200" Width="400" 
        WindowStartupLocation="CenterScreen" 
        ResizeMode="CanMinimize" Topmost="True">
    <Window.Resources>

    </Window.Resources>
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="AUTO" />
            <RowDefinition Height="AUTO" />
            <RowDefinition Height="AUTO" />
            <RowDefinition Height="AUTO" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBlock Text="Please wait ..." Grid.Row="1" Margin="6"/>

        <TextBlock Name="tbkStatus" Grid.Row="2" Margin="6" TextWrapping="Wrap" Text="{Binding StatusText}"/>

        <ProgressBar Grid.Row="3" Margin="6" Height="20"/>
        <Button Grid.Row="4" HorizontalAlignment="Center" Padding="24,3" Margin="6" Content="Stop"/>
    </Grid>
</Window>

Xaml only solution:

<TextBlock Text="{Binding StatusText}"
           MinWidth="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth}"
           HorizontalAlignment="Left"/>

This way whenever the Width growths, MinWidth growths too. Hence, the control can't shrink back.

I guess you could just listen to Layout Events like SizeChanged or LayoutUpdated or write some sort of behavior

In the below example, the basic premise is to listen to either of these events, and force your control to never shrink

Note this is totally untested and was just an idea, maybe you could set the MinWidth Property instead

Xaml

<TextBlock x:Name="tbkStatus" SizeChanged="OnSizeChanged"/>

Code Behind

private double _lastSize;

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
    var textBlock = sender as TextBlock;
    if (textBlock == null)
    {
        return;
    }

    if (e.WidthChanged)
    {
        if (textBlock.Width < _lastSize)
        {
            textBlock.Width = _lastSize;
        }
        _lastSize = textBlock.Width;
    }
}

Also Note

The SizeChangedEventArgs Class has many properties that you might be able to take advantage of

You can do something like this:

 <TextBlock Name="tbkStatus" Grid.Row="2" Margin="6" TextWrapping="Wrap" Text="{Binding StatusText}"/>

Since TextBlock doesn't have TextChange event this will do that job

DependencyPropertyDescriptor dp = DependencyPropertyDescriptor.FromProperty(TextBlock.TextProperty, typeof(TextBlock));
int textLength =0 


dp.AddValueChanged(tbkStatus, (object a, EventArgs b) =>
{
      if (textLength < tbkStatus.Text.Length)
      {
       textLength = tkbStatus.Text.Length;
       tbkStatus.Width = textLength * SomeValue; //You have to play around and see what value suits you best since it depends on font and it's size
      }

});

Alternatively, you can use a TextBox and make it read only and use the TextChanged event.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM