使用Viewbox来模糊背景

4
我正在制作一个类似于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网格”指的是矩形和图片的共同父级。我不能让它们成为祖先,否则会干扰模糊效果。所以我把它们放在一个网格中并排显示。
最后一部分是Multivalue转换器,用于实际计算VisualBrush视口的值。”
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调用中无法识别。但我已经尝试在转换中使用视图框的实际缩放比例,但没有成功。只要视图框存在,我就无法让它工作,所以我希望有人能想出问题出在哪里,或者甚至指向一个更简单的解决方案。 我想将该代码稍后转换为自定义控件,以便轻松重用,因此我更喜欢不太依赖任何特殊条件的方法。

1
+1 对于良好的研究和完整的代码...以及单词“layouting”。 - Charleh
1个回答

3
我通过将VisualBrush的Stretch更改为Fill而成功解决了奇怪的行为。

太棒了!这比我想象的要容易。我太专注于转换器和视图框,以至于甚至没有考虑到Stretch参数。非常感谢你! - dowhilefor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接