Rozmycie tła z Viewbox

buduję podobny efekt, który daje Ci szkło AERO, niewyraźne okno. Szybko zdałem sobie sprawę, że nie jest łatwo w WPF, ale udało mi się go uruchomić prawie całkowicie. Po prostu utknąłem, gdy zaangażowany jest Viewbox.

Tak więc zrobiłem: stworzyłem prostokąt, wykonałem pędzel wizualny, aby pobrać część danego elementu tła, przekonwertować okno podglądu, aby uzyskać dokładnie taką przestrzeń obrazu, że prostokąt nakłada się i użyć go jako wypełnienia prostokąta.

<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>

Siatka ElementName odnosi się do wspólnego rodzica mojego prostokąta i mojego obrazu. Nie mogę uczynić ich przodkami, w przeciwnym razie zakłóciłoby to efekt rozmycia. Więc umieszczam je obok siebie w siatce.

Ostatnia część to konwerter wielowartościowy, który dokonuje rzeczywistych obliczeń dla ViewBrush 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);
    }
}

To wszystko jest niezbędne do odtworzenia następującego problemu. Jeśli chcesz przetestować kod, możesz łatwo umieścić go w prostej aplikacji wpf.

Jeśli to przetestujesz, zobaczysz, że działa dobrze. Problem pojawia się teraz, jeśli umieścimy prostokąt w okienku Viewbox i siatkę o stałym rozmiarze (która naśladuje mój rzeczywisty problem).

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

Więc zgaduję, że skalowanie z okna podglądu jest stosowane po układaniu, więc nie zostanie rozpoznane w moich połączeniach TransformTo. Ale już próbowałem użyć rzeczywistego skalowania Viewboksa w moim konwertowaniu, ale bez powodzenia. Dopóki jest tam Viewbox, nie mogę go uruchomić, więc mam nadzieję, że każdy ma pomysł, co może być nie tak, a może nawet wskaże mi znacznie prostsze rozwiązanie. Chcę, aby ten kod został później przekonwertowany na niestandardowy element sterujący, aby łatwo go ponownie wykorzystać, więc preferuję sposoby, które nie zależą od specjalnych warunków.

questionAnswers(1)

yourAnswerToTheQuestion