我正在构建一个类似于AERO玻璃给你的效果,一个模糊的窗口。我很快意识到这在WPF中并不容易,但我设法让它几乎完全工作。当涉及到Viewbox时,我只是卡住了。
所以我所做的是:我创建了一个矩形,制作了一个视觉画笔来获取给定背景元素的一部分,转换viewbox以获取矩形重叠的图像空间,并将其用作矩形的填充。
<Grid x:Name="grid">
<Image x:Name="image" Source="someImage.png"/>
<Rectangle x:Name="blurBackgroundRect" Width="100" Height="100">
<Rectangle.Effect>
<BlurEffect Radius="10"/>
</Rectangle.Effect>
<Rectangle.Fill>
<VisualBrush
ViewboxUnits="Absolute"
AlignmentX="Center"
AlignmentY="Center"
Visual="{Binding ElementName=image}"
Stretch="None">
<VisualBrush.Viewbox>
<MultiBinding Converter="{StaticResource visualBrushTargetConverter}">
<Binding ElementName="grid"/>
<Binding ElementName="blurBackgroundRect"/>
<Binding ElementName="grid" Path="ActualWidth"/>
<Binding ElementName="grid" Path="ActualHeight"/>
</MultiBinding>
</VisualBrush.Viewbox>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>ElementName网格,引用我的矩形和图像的共同父元素。我不能让它们成为祖先,否则会影响模糊效果。所以我把它们放在一个网格里一个接一个。
最后一部分是多值转换器,它执行VisualBrush Viewbox的实际计算。
public class VisualBrushTargetConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var parentControl = values[0] as FrameworkElement;
var targetControl = values[1] as FrameworkElement;
var transformedPos = targetControl.TransformToVisual(parentControl).Transform(new Point());
var transformedSize = targetControl.TransformToVisual(parentControl).Transform(new Point(targetControl.RenderSize.Width, targetControl.RenderSize.Height));
transformedSize = new Point(transformedSize.X - transformedPos.X, transformedSize.Y - transformedPos.Y);
return new Rect(transformedPos.X,
transformedPos.Y,
transformedSize.X,
transformedSize.Y);
}
}因此,这些都是重现我下面的问题所必需的。如果您想测试代码,可以轻松地将其放入一个简单的wpf应用程序中。
如果您测试它,您会发现它工作得很好。如果我们将矩形放在一个Viewbox和一个固定大小的网格中(这模仿了我的实际问题),现在问题就出现了。
<Image x:Name="image" .../>
<Viewbox>
<Grid Width="800" Height="600">
<Rectangle x:Name="blurBackgroundRect" ...>
</Grid>
</Viewbox>所以我猜viewbox的缩放是在布局之后应用的,因此在我的TransformTo调用中不会被识别。但我已经尝试在我的convert中使用Viewbox的实际缩放,但没有成功。只要Viewbox在那里,我就不能让它工作,所以我希望有人知道哪里可能是错误的,或者甚至可以给我一个更简单的解决方案。我希望稍后将代码转换为自定义控件,以便轻松重用,因此我更喜欢不太依赖于任何特殊条件的方法。
发布于 2012-07-18 09:57:09
我能够通过将VisualBrush上的拉伸更改为Fill而不是None来修复奇怪的行为。
https://stackoverflow.com/questions/11524863
复制相似问题