阻止WPF TextBlock由于LayoutTransform而展开文本



我有一个应用程序,在该应用程序中,我将动态地向Canvas添加各种实例,并且底层Canvas具有缩放LayoutTransform。这对于矩形等视觉效果非常好,在矩形中,它们正确地保持固定的笔划宽度,但随着画布使用LayoutTransform"缩放",形状宽度/高度会扩展。然而,对于TextBlock实例,布局转换实际上是在缩放文本的呈现,使字体实际上更大。相反,我希望TextBlock的左上角原点通过布局转换进行转换,使文本保持相同大小。

以下是创建画布的ItemsControl的XAML:

            <ItemsControl ItemsSource="{Binding Annotations}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemContainerStyle>
                    <Style>
                        <Setter Property="Canvas.Left" Value="{Binding StartX}"/>
                        <Setter Property="Canvas.Top" Value="{Binding StartY}"/>                            
                    </Style>
                </ItemsControl.ItemContainerStyle>
                <ItemsControl.LayoutTransform>
                    <TransformGroup>
                        <ScaleTransform ScaleX="{Binding ZoomScale}" ScaleY="{Binding ZoomScale}" 
                                        CenterX="0.5" CenterY="0.5"/>
                    </TransformGroup>
                </ItemsControl.LayoutTransform>
            </ItemsControl>

以下是从绑定集合中呈现Annotations的一些数据模板:

    <DataTemplate DataType="{x:Type Annotations:RectangleAnnotation}">
        <Rectangle Width="{Binding Width}" Height="{Binding Height}" Stroke="Blue" IsHitTestVisible="False"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type Annotations:TextAnnotation}">
        <TextBlock Text="{Binding Text}" Foreground="Orange" IsHitTestVisible="False"/>
    </DataTemplate>

Annotation实例本身是具有相关绑定属性(TextAnnotation的StartX、StartY和Text)的简单INotifyPropertyChanged实现

我一直找不到任何简单的方法来防止文本的布局缩放。然而,在我开始破解解决方案之前,我想我应该检查一下:有人知道解决这个问题的干净方法吗?

每个变换都有一个反转属性,可以撤消其效果。因此,您可以将TextBlock的RenderTransform绑定到缩放Canvas的Transform的Inverse,这将撤消其对文本渲染的影响。

左上角通常是缩放的原点,因此如果全部为默认值,则文本应按指定移动到左上角。然而,如果您在画布上使用组合变换或不同的缩放中心,您可能需要稍微调整一下参数,但应该很容易编写一个转换器,它只采用变换的比例因子,以便在不移动缩放中心的情况下创建逆比例变换。

正如@hbarck所建议的,我无法绑定到Inverse,因为这是一个GeneralTransform而不是Transform。我通过按元素名称绑定到ScaleTransform并使用值转换器来反转缩放来解决这个问题:

    <Controls:InvertConverter x:Key="Invert"/>
    <DataTemplate DataType="{x:Type Annotations:TextAnnotation}">
        <TextBlock Text="{Binding Text}" Foreground="Orange" IsHitTestVisible="False">
            <TextBlock.RenderTransform>
                <ScaleTransform ScaleX="{Binding ScaleX, ElementName=AnnotationScale, Converter={StaticResource Invert}}"
                                ScaleY="{Binding ScaleY, ElementName=AnnotationScale, Converter={StaticResource Invert}}"/>
            </TextBlock.RenderTransform>
        </TextBlock>
    </DataTemplate>

和下面的转换器代码:

public sealed class InvertConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || value.GetType() != typeof(double) || targetType != typeof(double))
            return null;
        return 1/(double)value;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || value.GetType() != typeof(double) || targetType != typeof(double))
            return null;
        return 1 / (double)value;
    }
}

最新更新