【问题标题】:Draw diagonal Text/TextBlock/Label/Control in WPF relative to its container在 WPF 中相对于其容器绘制对角文本/文本块/标签/控件
【发布时间】:2023-11-03 20:42:01
【问题描述】:

我有一个动态大小的Grid。在里面我想画一个对角线 TextBlock 。我已经有一个对角线Path,您可以在其中设置LineGeometry 进行动态调整。但我在TextBlock 中找不到吊坠。我错过了什么吗?

<Grid>
    <TextBlock Text="Draft" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="180" FontWeight="Bold" Foreground="#FFA43A3A" RenderTransformOrigin="0.5,0.5"/>
    <Path Grid.Row="2" Grid.Column="0" Stroke="Red" StrokeThickness="2" Stretch="Fill">
        <Path.Data>
            <LineGeometry StartPoint="1,0" EndPoint="0,1" />                
        </Path.Data>            
    </Path>
</Grid>

预览

目标

这是我想要在不设置绝对 RotateTransform 的情况下拥有的东西。

两种解决方案的比较

red 前景是 FrankM 解决方案,green 来自 Henrik Hansen

https://imgur.com/a/92X0LXI

【问题讨论】:

    标签: c# wpf xaml expression-blend blend


    【解决方案1】:

    每当 Grid 的大小发生变化时,您都必须计算 TextBlock 的角度,例如使用转换器。

    这是一个例子:

    <Window x:Class="WpfApplication13.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApplication13"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <local:AngleConverter x:Key="AngleConverter"/>
        </Window.Resources>
        <Grid x:Name="grid">
            <TextBlock Text="Draft" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="120" FontWeight="Bold" Foreground="#FFA43A3A"
                       RenderTransformOrigin="0.5,0.5">
                <TextBlock.RenderTransform>
                    <MultiBinding Converter="{StaticResource AngleConverter}">
                        <MultiBinding.Bindings>
                            <Binding ElementName="grid" Path="ActualWidth"/>
                            <Binding ElementName="grid" Path="ActualHeight"/>
                        </MultiBinding.Bindings>
                    </MultiBinding>
                </TextBlock.RenderTransform>
            </TextBlock>
            <Path Stroke="Red" StrokeThickness="2" Stretch="Fill">
                <Path.Data>
                    <LineGeometry StartPoint="1,0" EndPoint="0,1" />
                </Path.Data>
            </Path>
        </Grid>
    </Window>
    

    转换器代码:

    using System;
    using System.Globalization;
    using System.Windows.Data;
    using System.Windows.Media;
    
    namespace WpfApplication13
    {
        public class AngleConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                double width = values[0] as double? ?? 0;
                double height = values[1] as double? ?? 0;
    
                double angleRadians = Math.Atan2(height, width);
                return new RotateTransform {Angle = - angleRadians * 180.0 / Math.PI};
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    }
    

    结果:

    【讨论】:

    • 我以为你没有多余的converter。还是谢谢!
    • @DominicJonas 这可以通过非常相似的方式在后面的代码中实现,但我认为这个解决方案在 WPF 中是非常合适和惯用的。
    【解决方案2】:

    您也可以将 TextBlock 包装在 ViewBox 中。它也会缩放文本,但这可能是不可取的?:

    <Viewbox Stretch="Fill" StretchDirection="Both">
      <TextBlock Text="Draft" FontWeight="Bold" Foreground="#FFA43A3A" Margin="5" RenderTransformOrigin="0.5,0.5" >
        <TextBlock.RenderTransform>
          <RotateTransform Angle="-35.0" />
        </TextBlock.RenderTransform>
      </TextBlock>
    </Viewbox>
    

    【讨论】:

    • Angle 应该是自动计算的,如果父级的大小发生变化,这将不起作用..
    • @DominicJonas:当我的机器上的尺寸发生变化时,它可以正常工作,ViewBox 调整角度 - 这就是添加它的重点:-)
    • 我刚刚测试了一下,发现虽然视角还变形了!如果你想要这个效果,那当然是一个解决方案!请参阅我的原始帖子进行直接比较。
    最近更新 更多