3

ウィンドウのどこかにコントロールがあります。このウィンドウのルートには、MainGridという名前のグリッドがあります。ScaleTransformメイングリッドのLayoutTransformに適用しました。これを使用して、ウィンドウのサイズが大きくなったときにウィンドウのすべてのコンテンツを拡大します。ただし、私のコントロールの1つは、BitmapCache描画パフォーマンスを最適化するためにキャンバスで使用しています。BitmapCacheは、コントロールに適用される可能性のあるものを考慮しないためScaleTransform、ズームインすると、コントロールがぼやけて表示されます。

BitmapCacheには、キャッシュされた画像のスケールを増やすために使用できるRenderAtScaleプロパティがあります。しかし、私が抱えている問題は、そのスケール値が何である必要があるかを見つけるためのエレガントな方法がわからないことです。今のところ、ウィンドウがそのスケール値をコントロールに渡すことができるように、コントロールにプロパティがあります。ただし、スケール値を渡す外部ソースに依存する必要がない場合は、それが必要です。

コントロールが適用されたすべてのScaleTransformsの要約を取得する方法はありますか?

4

5 に答える 5

3

PresentationSource'sを使用してRootVisual、要素の全体的な変換を計算できます。親と子の間に適用されるスケールを見つけるための一般的なパターンは次のとおりです。

Visual child = /* some visual */ this;
Visual parent = PresentationSource.FromVisual(child).RootVisual;

// calculate the transform needed to go from the parent to the child coordinate spaces
var childTransform = parent.TransformToDescendant(child);

// use the transform to scale a 1x1 rectangle
// use Inverse as the transform is from Parent coordinates to child, we want 
// child to parent
var unitRect = new Rectangle(0, 0, 1, 1);
var transformedUnit = childTransform.Inverse.TransformBounds(unitRect);

// transformedUnit.Width and transformedUnit.Height are now the scale factors (X and Y)
Debug.Assert(transformedUnit.Width == 0.25 && transformedUnit.Height == 0.25);
于 2013-10-05T07:44:40.513 に答える
2

Elad Katzの推奨に基づいて、VisualTreeをスキャンして均一なを合計しようとするコードを作成しましたScaleTransform。誰かがこのアルゴリズムのいくつかの最適化を持っているか、私が考慮していないかもしれないいくつかのことを考えることができるなら、私に知らせてください。繰り返しますが、私の目標は、現在適用されているを考慮して実際に適切なRenderAtScaleを取得することですScaleTransformOnRenderSizeChangedすべてのレイアウトが実行された後に発生するため、これを行うには問題ないようです。しかし、おそらくGetTotalTransformScale()をトリガーするためのより良い場所がありますか?

protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
    base.OnRenderSizeChanged(sizeInfo);
    double totalTransformScale = GetTotalTransformScale();
    BitmapCache bitmapCache = (BitmapCache)MyCachedCanvas.CacheMode;
    if (bitmapCache.RenderAtScale != totalTransformScale)
        bitmapCache.RenderAtScale = totalTransformScale;
}

private double GetTotalTransformScale()
{
    double totalTransform = 1.0d;    
    DependencyObject currentVisualTreeElement = this;            
    do
    {
        Visual visual = currentVisualTreeElement as Visual;
        if (visual != null)
        {
            Transform transform = VisualTreeHelper.GetTransform(visual);

            // This condition is a way of determining if it
            // was a uniform scale transform. Is there some better way?
            if ((transform != null) &&
                (transform.Value.M12 == 0) &&
                (transform.Value.M21 == 0) &&
                (transform.Value.OffsetX == 0) &&
                (transform.Value.OffsetY == 0) &&
                (transform.Value.M11 == transform.Value.M22))
            {                        
                totalTransform *= transform.Value.M11;
            }
        }
        currentVisualTreeElement = VisualTreeHelper.GetParent(currentVisualTreeElement);
    }
    while (currentVisualTreeElement != null);

    return totalTransform;
}
于 2011-03-01T00:49:01.173 に答える
2

Elad Katzが言ったように、aScaleTransformが親に適用されているかどうかを、それらを経由せずに直接知る方法はないと思います。

ただし、ScaleTransformがMainGridに適用されていることがわかっている場合は、MainGridのまたはにRenderAtScaleバインドScaleXできます。多分これはあなたがすでにしていることですが、とにかく私はそれをヒントとして投げますScaleYScaleTransform

おそらく、ScaleTransformバインディングでを参照する最も簡単な方法は、名前を付けることです。

<Grid Name="MainGrid">
    <Grid.LayoutTransform>
        <TransformGroup>
            <ScaleTransform x:Name="MainGridScaleTransform" .../>
        </TransformGroup>            
    </Grid.LayoutTransform>

バインディングは次のようになります

<BitmapCache RenderAtScale="{Binding ElementName=MainGridScaleTransform,
                                     Path=ScaleX}"/>

それ以外の場合はScaleTransform、パスに入ることができますTransformGroup

<BitmapCache RenderAtScale="{Binding ElementName=MainGrid,
 Path=(LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)}"/>

またはなしTransformGroup

<BitmapCache RenderAtScale="{Binding ElementName=MainGrid,
                              Path=(LayoutTransform).(ScaleTransform.ScaleX)}"/>
于 2011-02-27T16:17:21.170 に答える
1

コントロールのすべての親をいつでも再帰的に調べて、それらを合計することができますScaleTransform

他の方法ではできないと思います。

于 2011-02-27T05:26:56.483 に答える
0

これは古い質問ですが、私自身も同様の問題を抱えていましたScaleTransform。トップレベルのを無視するために、1つのタイプのコントロールを作成する必要がありました。

UIElementRenderTransform基本的にそれに影響を与えるプロパティを持っていますScaleTransform

于 2012-03-14T06:46:14.663 に答える