【问题标题】:Make a TextBlock use all available height before expand the width在扩展宽度之前使 TextBlock 使用所有可用高度
【发布时间】:2016-03-06 18:41:22
【问题描述】:

我有一个由 Style 定义的“英雄/垂直”按钮(内部带有图像):

<ControlTemplate TargetType="{x:Type controls:ImageButton}">
    <Grid MinHeight="{TemplateBinding MinHeight}" Background="{TemplateBinding Background}" Width="Auto" SnapsToDevicePixels="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <!-- Image -->
        <Viewbox x:Name="ViewBoxInternal" Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" IsEnabled="{TemplateBinding IsEnabled}"
                 Stretch="Uniform" StretchDirection="Both" Effect="{x:Null}"
                 Width="{TemplateBinding MaxSize}" Height="{TemplateBinding MaxSize}" 
                 MaxHeight="{TemplateBinding MaxSize}" MaxWidth="{TemplateBinding MaxSize}">
            <ContentPresenter ContentSource="{TemplateBinding Content}" Width="Auto" Height="Auto" 
                              HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Viewbox>

        <!-- Text -->
        <TextBlock x:Name="TextBlockInternal" Grid.Row="1"
                   HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="3,2,3,3"
                   VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Text="{TemplateBinding Text}" 
                   TextWrapping="Wrap" Effect="{TemplateBinding Effect}" TextAlignment="Center"/>
    </Grid>
</ControlTemplate>

用法:

<controls:ImageButton Text="Webcam Recording" Content="{StaticResource Vector.Camera.New}" 
          Margin="0" Height="70" MaxSize="30">

MaxSize控制控件内图片的最大尺寸。

示例图片:

预期图像:

我的问题:

我所有的垂直按钮的MaxWidth 为 60,English 没问题,问题从其他语言开始,当 60px 太小时,所以按钮应该横向变大,但仍然使用所有高度。

那么,如何让TextBlock 在扩展宽度之前使用所有可用高度?

TextWrapping 仅在没有可用宽度时起作用,例如当我将宽度设置为 60 时。

【问题讨论】:

    标签: wpf styles textblock dynamic-sizing


    【解决方案1】:

    有趣的问题。如果不知道最宽单词的宽度,您将不知道如何定义 TextBox 的宽度以获得所需的自动换行。要全力以赴,您可以使用一些语言 API 并使用它的分词器。对于我认为您的代码中的一个孤立案例,也许您可​​以自己执行此操作,并让 TextBox 自动调整大小、居中并达到您想要的结果。

    编写一个转换器来强制单词之间的中断。我把它放在一起来演示这项技术......当然,你会想要适应你的解决方案。

    代码

    public partial class MainWindow : Window
    {
        public string LongText
        {
            get { return (string)GetValue(LongTextProperty); }
            set { SetValue(LongTextProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for LongText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LongTextProperty =
            DependencyProperty.Register("LongText", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
    
    
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            Loaded += MainWindow_Loaded;
        }
    
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            LongText = "Some Really Long Text";
        }
    }
    
    public class WordBreakConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var text = (string)value;
            text = text.Replace(" ", Environment.NewLine);
            return text;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    XAML

    <Window.Resources>
        <local:WordBreakConverter x:Key="WordBreakConverter"/>
    </Window.Resources>
    
    <Grid x:Name="LayoutRoot">
        <StackPanel>
            <TextBlock Text="WPF" FontSize="36" Margin="20" Foreground="Orange" HorizontalAlignment="Center"/>
            <TextBlock Text="{Binding LongText, Converter={StaticResource WordBreakConverter}}" TextAlignment="Center"/>
        </StackPanel>
    </Grid>
    

    结果

    【讨论】:

    • 这个可以解决,但是有一个问题,这可能总是增加高度,而不增加宽度。也许我可以在Text 中添加一个\n,然后用NewLine 替换它在Converter 中。如果需要,这样我可以控制换行符。
    • 然而,Converter 对我的应用来说可能过于繁琐,因为有近 50 个垂直按钮分布在多个选项卡上。我正在考虑扩展TextBlock 并自己处理TextWrap
    • 转换器的性能将是最小的,并且很可能不明显。您当然可以将此技术扩展为“编码”您想要的 TextWrapping(例如在 X 字符之后查找第一个空格,因此“New Item”之类的文本是一行),或者直接将换行符放入您的字符串资源中。在不了解您的解决方案的情况下,我没有针对所有用例的通用答案。
    • 我会将转换器直接放入Style 以处理我的字符串资源中的所有\n。这样我就可以控制NewLine。谢谢。如果你想了解我目前的实现,请访问screentogif.codeplex.com
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 2012-08-08
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多