1

我有一个应用程序,我在其中动态地将各种实例添加到 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>

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

    <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 实例本身是简单的 INotifyPropertyChanged 实现,具有相关的绑定属性(TextAnnotation 的 StartX、StartY 和 Text。)

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

4

2 回答 2

2

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

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

于 2012-08-25T07:40:43.477 回答
1

正如@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;
    }
}
于 2012-08-26T14:41:47.703 回答