我有一个控件坐在窗口的某个地方。在这个窗口的根部是一个名为MainGrid的网格。我在MainGrid的LayoutTransform上应用了ScaleTransform
,当窗口大小增加时,我用它来放大窗口的所有内容。但是,我的一个控件在其画布上使用BitmapCache
来优化绘图性能。 BitmapCache没有考虑可能应用于控件的任何ScaleTransform
,所以如果我放大了,控件就会显得模糊。
BitmapCache确实有一个RenderAtScale属性,我可以使用它来增加缓存图像的比例。但是,我遇到的问题是我不知道找出Scale值需要的优雅方法。现在,我在我的控件上有一个属性,以便我的Window可以将其缩放值传递给控件。但是,如果我不需要依赖一些传递比例值的外部源,我想要它。
控件是否可以获取应用于它的所有ScaleTransforms的摘要?
答案 0 :(得分:3)
您可以使用PresentationSource
的{{1}}来计算元素的总转换。查找在父项和子项之间应用的比例的一般模式是
RootVisual
答案 1 :(得分:2)
正如 Elad Katz 所说,我认为没有任何直接的方法可以确定ScaleTransform
是否适用于任何父母而不经过它们。
但是,如果您知道ScaleTransform
已应用于MainGrid,那么您可以将RenderAtScale
绑定到MainGrid的ScaleX
或ScaleY
ScaleTransform
}。也许这就是你已经在做的事情,但无论如何我把它扔进了
在Binding中引用ScaleTransform
的最简单方法可能就是命名
<Grid Name="MainGrid">
<Grid.LayoutTransform>
<TransformGroup>
<ScaleTransform x:Name="MainGridScaleTransform" .../>
</TransformGroup>
</Grid.LayoutTransform>
Binding应该看起来与此类似
<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)}"/>
答案 2 :(得分:2)
根据Elad Katz的建议,我创建了一些代码来扫描VisualTree以尝试统一任何统一ScaleTransform
。如果任何人对这种算法有一些优化,或者可以想到一些我可能没有考虑的事情,请告诉我。同样,我的目标是在给定当前应用的ScaleTransform
的情况下获得实际上合适的RenderAtScale。 OnRenderSizeChanged
似乎是一个可以做到这一点的好地方,因为它发生在所有布局的东西运行之后。但是,也许有更好的地方可以触发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;
}
答案 3 :(得分:1)
您总是可以递归遍历所有Control的父母,并将他们的ScaleTransform
相加。
我认为你不能以任何其他方式做到这一点。
答案 4 :(得分:0)
我知道这是一个老问题,但我自己也遇到过类似的问题:我需要进行一种控制来忽略顶层的ScaleTransform
。
UIElement
具有RenderTransform
属性,基本上是影响它的ScaleTransform
。