0

The title might not be clear but I will explain now. I have a custom control that represents a modal (inspired by SingltonSean), When I trigger a command, it shows this modal that covers the rest of the elements behind it, it somewhat acts like a popup. Now I want everything behind it to be blurred. How can I achieve that?

This is my modal custom control:

<Style TargetType="{x:Type viewModel:Modal}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type viewModel:Modal}">
                <ControlTemplate.Resources>
                    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
                </ControlTemplate.Resources>
                <Grid Visibility="{TemplateBinding IsOpen, Converter={StaticResource BooleanToVisibilityConverter}}">
                    <Grid.Background>
                        <SolidColorBrush Color="Black" Opacity="0.025" />
                    </Grid.Background>
                    <Border HorizontalAlignment="Center" VerticalAlignment="Center" UseLayoutRounding="True"  BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
                            <Grid.OpacityMask>
                                <VisualBrush Visual="{Binding ElementName=border}" />
                            </Grid.OpacityMask>
                            <Border x:Name="border" Background="White" CornerRadius="20" />
                            <Grid Width="500" Height="600">
                                <StackPanel Width="300" HorizontalAlignment="Center" VerticalAlignment="Center">
                                    <Button Padding="10 5" Content="Close Modal" />
                                </StackPanel>
                            </Grid>
                        </Grid>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Robin Potter
  • 7
  • 1
  • 5
  • Does this answer your question? [Blur the background of the WPF container](https://stackoverflow.com/questions/7815278/blur-the-background-of-the-wpf-container) – Sinatr Jun 02 '21 at 10:23
  • It does not, because I am not using an image as a background. @Sinatr – Robin Potter Jun 02 '21 at 11:09
  • Have you read all answers? [This](https://stackoverflow.com/a/7817182/1997232) should do: the container behind should be blurred. – Sinatr Jun 02 '21 at 11:10
  • Sorry, it is not working either. Have you tried that solution on my code? – Robin Potter Jun 02 '21 at 11:19
  • No, but I am using blurr effect myself, similarly to that answer. What's not working? What you tried, what happend and what you want instead? – Sinatr Jun 02 '21 at 11:20
  • Under the Grid.Background tag I added this And it did not blur the background content. – Robin Potter Jun 02 '21 at 11:23
  • Is "background content" a part of the control? – Sinatr Jun 02 '21 at 11:24
  • No it is not. This custom control exists on top of other content. – Robin Potter Jun 02 '21 at 11:46
  • So why are you trying to add blur inside the control? Add blur to where content is. – Sinatr Jun 02 '21 at 11:52
  • What would be the best approach in your opinion? This custom control is reusable and if I go with your approach it will require me to add blur to the other content of every view every time I use that custom control. I thought maybe I can add a layer inside my custom control that is blurred above that content and then display the modal but it is not working for me. – Robin Potter Jun 02 '21 at 12:34
  • See my answer, that's what the second part of it attempts to achieve using attached behavior. You can't encapsulate blur effect inside (afaik), but you can apply it to something outside of your control. There is still work to do: un-blurring and using another approach than `ElementName` to pass instance of container you want to blur, but should be a good starter. – Sinatr Jun 02 '21 at 12:38

1 Answers1

1

You need to apply blur where content is:

<Grid>
    <Grid>
        <Grid.Effect>
            <BlurEffect Radius="20"/>
        </Grid.Effect>
        <TextBlock Text="Some content I want to blur"/>
    </Grid>
    <TextBlock Text="Popup"/>
</Grid>

If you want to make a control, which is able to blur something before in visual tree, you still need to apply effect to it. One possibility is to use attached behavior:

public static class Behavior
{
    public static UIElement GetBlurTarget(DependencyObject obj) => (UIElement)obj.GetValue(BlurTargetProperty);
    public static void SetBlurTarget(DependencyObject obj, UIElement value) => obj.SetValue(BlurTargetProperty, value);

    public static readonly DependencyProperty BlurTargetProperty =
        DependencyProperty.RegisterAttached("BlurTarget", typeof(UIElement), typeof(Behavior), new PropertyMetadata((d, e) =>
        {
            if (e.NewValue is UIElement element)
                element.Effect = new BlurEffect { Radius = 20 };
        }));
}

Then layout should be like this:

<Grid>
    <Grid x:Name="container">
        <TextBlock Text="Some content I want to blur" />
    </Grid>
    <TextBlock Text="Popup" local:Behavior.BlurTarget="{Binding ElementName=container}"/>
</Grid>

Both cases will produce same result:

Sinatr
  • 20,892
  • 15
  • 90
  • 319