4

AEROガラスが提供するのと同様の効果、ぼやけたウィンドウを構築しています。これはWPFでは簡単ではないことにすぐに気付きましたが、ほぼ完全に機能させることができました。ビューボックスが関係しているときに私は立ち往生しています。

つまり、長方形を作成し、視覚的なブラシを作成して特定の背景要素の一部を取得し、ビューボックスを変換して、長方形が重なる画像のスペースを正確に取得し、それを長方形の塗りつぶしとして使用しました。

<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ビューボックスの実際の計算を行うMultivalueコンバーターです。

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アプリケーションに簡単に配置できます。

これをテストすると、正常に機能していることがわかります。ビューボックス内に長方形を配置し、固定サイズのグリッドを配置すると、問題が発生します(これは私の実際の問題を模倣しています)。

<Image x:Name="image" .../>
<Viewbox>
    <Grid Width="800" Height="600">
        <Rectangle x:Name="blurBackgroundRect" ...>
    </Grid>
</Viewbox>

したがって、ビューボックスからのスケーリングはレイアウト後に適用されると推測しているため、TransformTo呼び出しでは認識されません。しかし、私はすでに変換でビューボックスの実際のスケーリングを使用しようとしましたが、運がありませんでした。ビューボックスがそこにある限り、私はそれを機能させることができないので、誰かが何が間違っている可能性があるのか​​を知っているか、もっと簡単な解決策を教えてくれることを願っています。そのコードを後でカスタムコントロールに変換して、それを簡単に再利用できるようにしたいので、特別な条件にあまり依存しない方法を好みます。

4

1 に答える 1

3

VisualBrushのStretchをNoneではなくFillに変更することで、奇妙な動作を修正することができました。

于 2012-07-18T01:57:09.480 に答える