1

さまざまなインスタンスをCanvasに動的に追加し、基になるCanvasにスケーリングLayoutTransformがあるアプリケーションがあります。これは、長方形のようなビジュアルに最適です。長方形のように、固定のストローク幅を正しく維持しますが、キャンバスがLayoutTransformで「ズーム」されると、シェイプの幅/高さが拡大します。ただし、TextBlockインスタンスの場合、レイアウト変換は実際にはテキストのレンダリングをスケーリングし、フォントを効果的に大きくします。代わりに私がしたいのは、TextBlockの左上の原点をレイアウト変換で変換し、テキストを同じサイズのままにすることです。

Canvasを作成する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インスタンス自体は、関連するバインドされたプロパティ(TextAnnotationのStartX、StartY、およびText)を持つ単純なINotifyPropertyChanged実装です。

テキストのレイアウトスケーリングを防ぐ簡単な方法を見つけることができませんでした。しかし、私が解決策への道をハッキングし始める前に、私はチェックしたいと思いました:誰かがこれを修正するためのクリーンな方法を知っていますか?

4

2 に答える 2

2

すべての変換には、その効果を元に戻す逆プロパティがあります。したがって、TextBlockのRenderTransformを、CanvasをスケーリングするInverse of the Transformにバインドできます。これにより、テキストレンダリングへの影響が元に戻されます。

通常、左上隅がスケーリングの原点であるため、すべてがデフォルトの場合、テキストは指定したとおりに左上隅に移動する必要があります。ただし、組み合わせた変換またはキャンバス上の別のズームセンターを使用している場合は、パラメータを少し試す必要があるかもしれませんが、たとえば、変換のスケール係数のみを使用するコンバータを作成するのは非常に簡単です。ズームの中心をシフトせずに逆スケール変換を作成するため。

于 2012-08-25T07:40:43.477 に答える
1

@hbarckが示唆したように、これはTransformではなくGeneralTransformであったため、Inverseにバインドできませんでした。要素名で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 に答える