我有一个应用程序,在该应用程序中,我将动态地向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;
}
}