4

我正在构建 AERO 玻璃给你的类似效果,一个模糊的窗户。我很快意识到这在 WPF 中并不容易,但我设法让它几乎完全工作。当涉及 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>

所以我猜测视图框的缩放是在布局之后应用的,因此在我的 TransformTo 调用中不会被识别。但是我已经尝试在我的转换中使用 Viewbox 的实际缩放,但没有运气。只要 Viewbox 在那里,我就无法让它工作,所以我希望任何人都知道可能出了什么问题,或者甚至可以为我指出一个更简单的解决方案。我希望该代码稍后转换为自定义控件,以便轻松重用它,因此我更喜欢不太依赖任何特殊条件的方法。

4

1 回答 1

3

我能够通过将 VisualBrush 上的 Stretch 更改为 Fill 而不是 None 来修复奇怪的行为。

于 2012-07-18T01:57:09.480 回答