【问题标题】:C# UWP Toolkit DropShadowPanel inner shadowC# UWP Toolkit DropShadowPanel 内阴影
【发布时间】:2018-01-05 18:52:52
【问题描述】:

在C# UWP中如何制作内阴影效果?

像这样:

我创建了一个只有边框的网格,但阴影填充了整个网格。

<controls:DropShadowPanel     BlurRadius="5"
                              ShadowOpacity="0.5"
                              OffsetX="0"
                              OffsetY="0"
                              Color="Black">
    <Grid BorderBrush="White" BorderThickness="5"/>
</controls:DropShadowPanel>

如何用这个控件制作内阴影效果?

【问题讨论】:

    标签: c# xaml uwp dropshadow windows-community-toolkit


    【解决方案1】:

    注意DropShadowPanel 可以掩盖Rectangle,因此您可以创建一个无填充 Rectangle 并将其放置在DropShadowPanel 中,从而为@987654327 创建一个扩展阴影仅限@的边框。然后,您只需将其放在Grid 内并剪裁Grid 以切断外部阴影。如果您想要背景颜色,只需将另一个 Rectangle 添加到 Grid 并将其放在 DropShadowPanel 后面。

    示例代码

    <Grid Width="400"
          Height="200"
          Margin="24">
        <Grid.Clip>
            <RectangleGeometry Rect="0,0,400,200" />
        </Grid.Clip>
        <Rectangle x:Name="BackgroundColor"
                   Fill="LightSteelBlue" />
        <controls:DropShadowPanel x:Name="InnerShadow"
                                  HorizontalContentAlignment="Stretch"
                                  BlurRadius="15"
                                  ShadowOpacity="0.5"
                                  Color="Black">
            <Rectangle x:Name="BorderColor"
                       Stroke="LightGray"
                       StrokeThickness="10" />
        </controls:DropShadowPanel>
    </Grid>
    

    结果


    关于剪辑

    需要注意的一点是,每当Grid 的大小发生变化时,您都需要手动更新Rect 的大小。或者,您可以使用新的 Composition API 进行剪辑 -

    var visual = ElementCompositionPreview.GetElementVisual(RootGrid);
    var compositor = visual.Compositor;
    visual.Clip = compositor.CreateInsetClip();
    

    【讨论】:

      【解决方案2】:

      我也遇到了同样的问题,并最终为它创建了自己的控件。我基本上创建了一个有四个细边框的网格,每边一个(左、右、上、下),每个都有一个线性渐变画笔来创建阴影效果。像这样:

      这里是代码::

      using Windows.UI;
      using Windows.UI.Xaml;
      using Windows.UI.Xaml.Controls;
      using Windows.UI.Xaml.Media;
      
      namespace TestInnerDropShadow
      {
          [TemplatePart(Name = PARTNAME_LEFT_BORDER, Type = typeof(Border))]
          [TemplatePart(Name = PARTNAME_RIGHT_BORDER, Type = typeof(Border))]
          [TemplatePart(Name = PARTNAME_TOP_BORDER, Type = typeof(Border))]
          [TemplatePart(Name = PARTNAME_BOTTOM_BORDER, Type = typeof(Border))]
          [TemplatePart(Name = PARTNAME_LEFT_GRADIENT, Type = typeof(GradientStop))]
          [TemplatePart(Name = PARTNAME_RIGHT_GRADIENT, Type = typeof(GradientStop))]
          [TemplatePart(Name = PARTNAME_TOP_GRADIENT, Type = typeof(GradientStop))]
          [TemplatePart(Name = PARTNAME_BOTTOM_GRADIENT, Type = typeof(GradientStop))]
          public class InnerDropShadowPanel : ContentControl
          {
              internal const string PARTNAME_LEFT_BORDER = "PART_LeftBorder";
              internal const string PARTNAME_RIGHT_BORDER = "PART_RightBorder";
              internal const string PARTNAME_TOP_BORDER = "PART_TopBorder";
              internal const string PARTNAME_BOTTOM_BORDER = "PART_BottomBorder";
      
              internal const string PARTNAME_LEFT_GRADIENT = "PART_LeftGradient";
              internal const string PARTNAME_RIGHT_GRADIENT = "PART_RightGradient";
              internal const string PARTNAME_TOP_GRADIENT = "PART_TopGradient";
              internal const string PARTNAME_BOTTOM_GRADIENT = "PART_BottomGradient";
      
              protected override void OnApplyTemplate()
              {
                  base.OnApplyTemplate();
                  UpdateShadowDimensions();
                  UpdateShadowColor();
              }
      
              private static void OnPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
              {
                  if (o is InnerDropShadowPanel thisControl)
                  {
                      var updateLeft = (e.Property == ShadowOpacityProperty || e.Property == BlurRadiusLeftProperty);
                      var updateRight = (e.Property == ShadowOpacityProperty || e.Property == BlurRadiusRightProperty);
                      var updateTop = (e.Property == ShadowOpacityProperty || e.Property == BlurRadiusTopProperty);
                      var updateBottom = (e.Property == ShadowOpacityProperty || e.Property == BlurRadiusBottomProperty);
                      thisControl.UpdateShadowDimensions(updateLeft, updateRight, updateTop, updateBottom);
                  }
              }
      
              private void UpdateShadowDimensions(bool updateLeft = true, bool updateRight = true, bool updateTop = true, bool updateBottom = true)
              {
                  if (updateLeft && GetTemplateChild(PARTNAME_LEFT_BORDER) is Border left)
                  {
                      left.Width = BlurRadiusLeft;
                      left.Opacity = ShadowOpacity;
                  }
      
                  if (updateRight && GetTemplateChild(PARTNAME_RIGHT_BORDER) is Border right)
                  {
                      right.Width = BlurRadiusRight;
                      right.Opacity = ShadowOpacity;
                  }
      
                  if (updateTop && GetTemplateChild(PARTNAME_TOP_BORDER) is Border top)
                  {
                      top.Height = BlurRadiusTop;
                      top.Opacity = ShadowOpacity;
                  }
      
                  if (updateBottom && GetTemplateChild(PARTNAME_BOTTOM_BORDER) is Border bottom)
                  {
                      bottom.Height = BlurRadiusBottom;
                      bottom.Opacity = ShadowOpacity;
                  }
              }
      
              private void UpdateShadowColor()
              {
                  if (GetTemplateChild(PARTNAME_LEFT_GRADIENT) is GradientStop left)
                      left.Color = ShadowColor;
      
                  if (GetTemplateChild(PARTNAME_RIGHT_GRADIENT) is GradientStop right)
                      right.Color = ShadowColor;
      
                  if (GetTemplateChild(PARTNAME_TOP_GRADIENT) is GradientStop top)
                      top.Color = ShadowColor;
      
                  if (GetTemplateChild(PARTNAME_BOTTOM_GRADIENT) is GradientStop bottom)
                      bottom.Color = ShadowColor;
              }
      
              #region ShadowOpacity Dependency Property
      
              public static readonly DependencyProperty ShadowOpacityProperty = DependencyProperty.Register(
                  nameof(ShadowOpacity),
                  typeof(double),
                  typeof(InnerDropShadowPanel),
                  new PropertyMetadata(0d, OnPropertyChanged));
      
              public double ShadowOpacity
              {
                  get => (double)GetValue(ShadowOpacityProperty);
                  set => SetValue(ShadowOpacityProperty, value);
              }
      
              #endregion
      
              #region ShadowColor Dependency Property
      
              public static readonly DependencyProperty ShadowColorProperty = DependencyProperty.Register(
                  nameof(ShadowColor),
                  typeof(Color),
                  typeof(InnerDropShadowPanel),
                  new PropertyMetadata(Colors.Transparent, OnShadowColorChanged));
      
              public Color ShadowColor
              {
                  get => (Color)GetValue(ShadowColorProperty);
                  set => SetValue(ShadowColorProperty, value);
              }
      
              private static void OnShadowColorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
              {
                  if (o is InnerDropShadowPanel thisControl)
                  {
                      thisControl.UpdateShadowColor();
                  }
              }
      
              #endregion
      
              #region BlurRadiusLeft Dependency Property
      
              public static readonly DependencyProperty BlurRadiusLeftProperty = DependencyProperty.Register(
                  nameof(BlurRadiusLeft),
                  typeof(double),
                  typeof(InnerDropShadowPanel),
                  new PropertyMetadata(0d, OnPropertyChanged));
      
              public double BlurRadiusLeft
              {
                  get => (double)GetValue(BlurRadiusLeftProperty);
                  set => SetValue(BlurRadiusLeftProperty, value);
              }
      
              #endregion
      
              #region BlurRadiusRight Dependency Property
      
              public static readonly DependencyProperty BlurRadiusRightProperty = DependencyProperty.Register(
                  nameof(BlurRadiusRight),
                  typeof(double),
                  typeof(InnerDropShadowPanel),
                  new PropertyMetadata(0d, OnPropertyChanged));
      
              public double BlurRadiusRight
              {
                  get => (double)GetValue(BlurRadiusRightProperty);
                  set => SetValue(BlurRadiusRightProperty, value);
              }
      
              #endregion
      
              #region BlurRadiusTop Dependency Property
      
              public static readonly DependencyProperty BlurRadiusTopProperty = DependencyProperty.Register(
                  nameof(BlurRadiusTop),
                  typeof(double),
                  typeof(InnerDropShadowPanel),
                  new PropertyMetadata(0d, OnPropertyChanged));
      
              public double BlurRadiusTop
              {
                  get => (double)GetValue(BlurRadiusTopProperty);
                  set => SetValue(BlurRadiusTopProperty, value);
              }
      
              #endregion
      
              #region BlurRadiusBottom Dependency Property
      
              public static readonly DependencyProperty BlurRadiusBottomProperty = DependencyProperty.Register(
                  nameof(BlurRadiusBottom),
                  typeof(double),
                  typeof(InnerDropShadowPanel),
                  new PropertyMetadata(0d, OnPropertyChanged));
      
              public double BlurRadiusBottom
              {
                  get => (double)GetValue(BlurRadiusBottomProperty);
                  set => SetValue(BlurRadiusBottomProperty, value);
              }
      
              #endregion
          }
      }
      

      以及控制模板:

          <Style TargetType="local:InnerDropShadowPanel">
              <Setter Property="Template">
                  <Setter.Value>
                      <ControlTemplate TargetType="local:InnerDropShadowPanel">
                          <Grid>
      
                              <ContentPresenter/>
                              
                              <Border x:Name="PART_LeftBorder"
                                      Opacity="0.5"
                                      HorizontalAlignment="Left"
                                      VerticalAlignment="Stretch">
                                  <Border.Background>
                                      <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                                          <GradientStop Color="Black" Offset="0" x:Name="PART_LeftGradient"/>
                                          <GradientStop Color="Transparent" Offset="0.5"/>
                                      </LinearGradientBrush>
                                  </Border.Background>
                              </Border>
      
                              <Border x:Name="PART_RightBorder"
                                      Opacity="0.5"
                                      HorizontalAlignment="Right"
                                      VerticalAlignment="Stretch">
                                  <Border.Background>
                                      <LinearGradientBrush StartPoint="1,0" EndPoint="0,0">
                                          <GradientStop Color="Black" Offset="0" x:Name="PART_RightGradient"/>
                                          <GradientStop Color="Transparent" Offset="0.5"/>
                                      </LinearGradientBrush>
                                  </Border.Background>
                              </Border>
      
                              <Border x:Name="PART_TopBorder"
                                      Opacity="0.5"
                                      HorizontalAlignment="Stretch"
                                      VerticalAlignment="Top">
                                  <Border.Background>
                                      <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                          <GradientStop Color="Black" Offset="0" x:Name="PART_TopGradient"/>
                                          <GradientStop Color="Transparent" Offset="0.5"/>
                                      </LinearGradientBrush>
                                  </Border.Background>
                              </Border>
      
                              <Border x:Name="PART_BottomBorder"
                                      Opacity="0.5"
                                      HorizontalAlignment="Stretch"
                                      VerticalAlignment="Bottom">
                                  <Border.Background>
                                      <LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
                                          <GradientStop Color="Black" Offset="0" x:Name="PART_BottomGradient"/>
                                          <GradientStop Color="Transparent" Offset="0.5"/>
                                      </LinearGradientBrush>
                                  </Border.Background></Border>
      
                          </Grid>
                      </ControlTemplate>
                  </Setter.Value>
              </Setter>
          </Style>
      

      像这样使用 XAML:

          <local:InnerDropShadowPanel HorizontalAlignment="Center"
                                      BlurRadiusLeft="6"
                                      BlurRadiusTop="6"
                                      ShadowOpacity="0.4"
                                      ShadowColor="Black">
              <TextBlock Text="Test"
                         Foreground="Black"
                         FontSize="120"
                         Margin="50,20"/>
          </local:InnerDropShadowPanel>
      

      你会得到这样的东西:

      您可以在任何一侧或全部添加阴影,并整体更改阴影的颜色和不透明度:

          <local:InnerDropShadowPanel HorizontalAlignment="Center"
                                      BlurRadiusLeft="6"
                                      BlurRadiusTop="6"
                                      BlurRadiusBottom="50"
                                      BlurRadiusRight="100"
                                      ShadowOpacity="1"
                                      ShadowColor="Red">
              <TextBlock Text="Test"
                         Foreground="Black"
                         FontSize="120"
                         Margin="50,20"/>
          </local:InnerDropShadowPanel>
      

      给你这个:

      我相信您可以修改此控件并通过添加自定义设置来狂野,例如,每一面都有不同的颜色或不透明度。不过,对于绝大多数情况,上述解决方案可能就足够了。

      【讨论】:

        【解决方案3】:
        protected override CreateParams CreateParams
            {
                get
                {
                    const int CS_DROPSHADOW = 0x20000;
                    CreateParams cp = base.CreateParams;
                    cp.ClassStyle |= CS_DROPSHADOW;
                    return cp;
                }
            }
        

        【讨论】:

        • 感谢您提供此代码 sn-p,它可能会提供一些有限的短期帮助。一个正确的解释would greatly improve 它的长期价值,通过展示为什么这是一个很好的解决问题的方法,并且会使其对未来有其他类似问题的读者更有用。请编辑您的答案以添加一些解释,包括您所做的假设
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-13
        • 1970-01-01
        相关资源
        最近更新 更多