WPF: Border, CornerRadius oraz przycinanie zawartości

Ostatnio potrzebowałem użyć Border z CornerRadius ustawionym na jakąś wartość, aby móc potem umieścić w środku inne kontrolki (np. obrazek). Moje pierwsze podejście było następujące:

<Border CornerRadius="50" BorderBrush="Black" BorderThickness="2">
  <Image Stretch="Fill" Source="http://i.zdnet.com/blogs/win7-wallpaper-small.png"></Image>
</Border>

Niestety w taki sposób zawartość Border nie zostanie poprawnie przycięta i efekt jest następujący:

image

Znalazłem na forum bardzo ciekawe rozwiązanie z użyciem OpacityMask. Najpierw kod a potem wyjaśnienie:

<Border CornerRadius="50" BorderBrush="Black" BorderThickness="2">
  <Grid>
      <Border CornerRadius="50" Background="White" BorderThickness="2" x:Name="mask"/>
      
      <Image Stretch="Fill" Source="http://i.zdnet.com/blogs/win7-wallpaper-small.png">
              <Image.OpacityMask>
                  <VisualBrush Visual="{Binding ElementName=mask}"></VisualBrush>
              </Image.OpacityMask>
          </Image>
  </Grid>
</Border>

Efekt:

image

Aby zrozumieć powyższy kod należy najpierw wyjaśnić jak działa OpacityMask. OpacityMask to brush, który określa, co na docelowym obrazku będzie wyświetlone. Myślę, że poniższy obrazek z MSDN jest doskonałym wyjaśnieniem:

Object with a LinearGradientBrush opacity mask

Innymi słowy, OpacityMask służy do ustawiania przezroczystości poszczególnych pikseli.

W naszym przypadku korzystamy z VisualBrush, który wygeneruje pędzel na podstawie innej kontrolki. Stworzyliśmy drugą kontrolkę border jako maskę. Posiada ona ten sam CornerRadius, co oznacza, że po wygenerowaniu pędzla, rogi kontrolki będą przezroczyste! I o to właśnie chodzi – po nałożeniu tej maski na obrazek, przytniemy odpowiednio narożniki. To co było przezroczyste w kontrolce “mask” (narożniki) będzie również niewidzialne na docelowym elemencie (obrazku).

One thought on “WPF: Border, CornerRadius oraz przycinanie zawartości”

Leave a Reply

Your email address will not be published.