Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ShadowPanel (New Control) #4006

Closed
AbdAlghaniAlbiek opened this issue Apr 28, 2021 · 7 comments
Closed

ShadowPanel (New Control) #4006

AbdAlghaniAlbiek opened this issue Apr 28, 2021 · 7 comments
Labels
duplicate 👥 Indicates that identical Issue or PR already exist feature request 📬 A request for new changes to improve functionality need more info 📌

Comments

@AbdAlghaniAlbiek
Copy link

AbdAlghaniAlbiek commented Apr 28, 2021

I was using DropDownShadow it works perfect on any UIElement but when I change CornerRadius value of any kind of panel (Grid, StackPanel, .....) the shadow still with sharp edges
then I noticed that it works with rectangle when I change RadiusX and RadiusY the shadow will be with rounded corners, that because DropDownShadow use composition effects and composition take a mask for the control itself , when composition make a shadow mask it use GetAlphaMask method that is available in Rectangle control and not available in panels controls, that is the reason of response of shadow for corner changes in rectangle and not response for panels' corners changes

I find out another way to do that is making a completely new control depends on two layers
layer for shadow
layer for content

The xaml code will be something like this:

    <Grid x:Name="shadowGrid"
          HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch"
          CornerRadius="{Binding ElementName=rootElement, Path=CornerRadius}">
        <Grid.Background>
            <SolidColorBrush Color="{Binding ElementName=userCon, Path=ShadowColor}"
                             Opacity="{Binding ElementName=userCon, Path=ShadowOpacity}"/>
        </Grid.Background>
    </Grid>

    <ContentPresenter x:Name="contentGrid"
          Content="{Binding ElementName=userCon, Path=InnerContent}"
          Margin="{Binding ElementName=userCon, Path=Padding}"
          CornerRadius="{Binding ElementName=rootElement, Path=CornerRadius}"
          HorizontalAlignment="{Binding ElementName=userCon, Path=HorizontalContentAlignment}"
          VerticalAlignment="{Binding ElementName=userCon, Path=VerticalContentAlignment}">
    </ContentPresenter>
</Grid>

And the dependencies properties in Code behind:

#region Background
public new SolidColorBrush Background
{
get { return (SolidColorBrush)GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty BackgroundProperty =
        DependencyProperty.Register("Background", typeof(SolidColorBrush), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region Width 
    public new double Width
    {
        get { return (double)GetValue(WidthProperty); }
        set { SetValue(WidthProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty WidthProperty =
        DependencyProperty.Register("Width", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region Height 
    public new double Height
    {
        get { return (double)GetValue(HeightProperty); }
        set { SetValue(HeightProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty HeightProperty =
        DependencyProperty.Register("Height", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region BorderThickness 
    public new Thickness BorderThickness
    {
        get { return (Thickness)GetValue(BorderThicknessProperty); }
        set { SetValue(BorderThicknessProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty BorderThicknessProperty =
        DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region BorderBrush 
    public new SolidColorBrush BorderBrush
    {
        get { return (SolidColorBrush)GetValue(BorderBrushProperty); }
        set { SetValue(BorderBrushProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty BorderBrushProperty =
        DependencyProperty.Register("BorderBrush", typeof(SolidColorBrush), typeof(ShadowPanel), new PropertyMetadata(0));


    #endregion

    #region HorizontalAlignment 
    public new HorizontalAlignment HorizontalAlignment
    {
        get { return (HorizontalAlignment)GetValue(HorizontalAlignmentProperty); }
        set { SetValue(HorizontalAlignmentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty HorizontalAlignmentProperty =
        DependencyProperty.Register("HorizontalAlignment", typeof(HorizontalAlignment), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region VerticalAlignment 
    public new VerticalAlignment VerticalAlignment
    {
        get { return (VerticalAlignment)GetValue(VerticalAlignmentProperty); }
        set { SetValue(VerticalAlignmentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty VerticalAlignmentProperty =
        DependencyProperty.Register("VerticalAlignment", typeof(VerticalAlignment), typeof(ShadowPanel), new PropertyMetadata(0));


    #endregion

    #region HorizontalContentAlignment 

    public new HorizontalAlignment HorizontalContentAlignment
    {
        get { return (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty); }
        set { SetValue(HorizontalContentAlignmentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty HorizontalContentAlignmentProperty =
        DependencyProperty.Register("HorizontalContentAlignment", typeof(HorizontalAlignment), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region VerticalContentAlignment 
    public new VerticalAlignment VerticalContentAlignment
    {
        get { return (VerticalAlignment)GetValue(VerticalContentAlignmentProperty); }
        set { SetValue(VerticalContentAlignmentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty VerticalContentAlignmentProperty =
        DependencyProperty.Register("VerticalContentAlignment", typeof(VerticalAlignment), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region CornerRadius 
    public new CornerRadius CornerRadius
    {
        get { return (CornerRadius)GetValue(CornerRadiusProperty); }
        set { SetValue(CornerRadiusProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty CornerRadiusProperty =
        DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region InnerContent 
    public new UIElement InnerContent
    {
        get { return (UIElement)GetValue(InnerContentProperty); }
        set { SetValue(InnerContentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for InnerContent.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty InnerContentProperty =
        DependencyProperty.Register("InnerContent", typeof(UIElement), typeof(ShadowPanel), new PropertyMetadata(0));


    #endregion

    #region Padding
    public new Thickness Padding
    {
        get { return (Thickness)GetValue(PaddingProperty); }
        set { SetValue(PaddingProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ContentPadding.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty PaddingProperty =
        DependencyProperty.Register("ContentPadding", typeof(Thickness), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region ShadowColor
    public Windows.UI.Color ShadowColor
    {
        get { return (Windows.UI.Color)GetValue(ShadowColorProperty); }
        set { SetValue(ShadowColorProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ShadowColor.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ShadowColorProperty =
        DependencyProperty.Register("ShadowColor", typeof(Windows.UI.Color), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region ShadowOpacity

    public double ShadowOpacity
    {
        get { return (double)GetValue(ShadowOpacityProperty); }
        set { SetValue(ShadowOpacityProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ShadowOpacity.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ShadowOpacityProperty =
        DependencyProperty.Register("ShadowOpacity", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0));

    #endregion

    #region ShadowBlur

    public double ShadowBlur
    {
        get { return (double)GetValue(ShadowBlurProperty); }
        set { SetValue(ShadowBlurProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ShadowBlur.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ShadowBlurProperty =
        DependencyProperty.Register("ShadowBlur", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0, OnShadowBlurPropertyChanged));

    private static void OnShadowBlurPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

    }


    #endregion

    #region ShadowOffsetX
    public double ShadowOffsetX
    {
        get { return (double)GetValue(ShadowOffsetXProperty); }
        set { SetValue(ShadowOffsetXProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ShadowOffset.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ShadowOffsetXProperty =
        DependencyProperty.Register("ShadowOffsetX", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0, OnShadowOffsetXPropertyChanged));

    private static void OnShadowOffsetXPropertyChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
    {
        Grid shadowGrid = UIAssistance.FindChild<Grid>(((ShadowPanel)s).Content, "shadowGrid");

        shadowGrid.Margin =
            new Thickness(-(double)e.NewValue, shadowGrid.Margin.Top, shadowGrid.Margin.Right, shadowGrid.Margin.Bottom);
    }
    #endregion

    #region ShadowOffsetY
    public double ShadowOffsetY
    {
        get { return (double)GetValue(ShadowOffsetYProperty); }
        set { SetValue(ShadowOffsetYProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ShadowOffset.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ShadowOffsetYProperty =
        DependencyProperty.Register("ShadowOffsetY", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0, OnShadowOffsetYPropertyChanged));

    private static void OnShadowOffsetYPropertyChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
    {
        Grid shadowGrid = UIAssistance.FindChild<Grid>(((ShadowPanel)s).Content, "shadowGrid");

        shadowGrid.Margin =
           new Thickness(shadowGrid.Margin.Top, -(double)e.NewValue, shadowGrid.Margin.Right, shadowGrid.Margin.Bottom);
    }
    #endregion

    #region TopLeftCornerRadius
    public double TopLeftCornerRadius
    {
        get { return (double)GetValue(TopLeftCornerRadiusProperty); }
        set { SetValue(TopLeftCornerRadiusProperty, value); }
    }

    // Using a DependencyProperty as the backing store for LeftCorner.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TopLeftCornerRadiusProperty =
        DependencyProperty.Register("TopLeftCornerRadius", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0, OnTopLeftCornerRadiusPropertyChanged));

    private static void OnTopLeftCornerRadiusPropertyChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
    {
        ((UserControl)s).CornerRadius =
            new CornerRadius((double)e.NewValue, ((UserControl)s).CornerRadius.TopRight,
                            ((ShadowPanel)s).CornerRadius.BottomRight, ((UserControl)s).CornerRadius.BottomLeft);
    }

    #endregion

    #region TopRightCornerRadius
    public double TopRightCornerRadius
    {
        get { return (double)GetValue(TopRightCornerRadiusProperty); }
        set { SetValue(TopRightCornerRadiusProperty, value); }
    }

    // Using a DependencyProperty as the backing store for LeftCorner.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TopRightCornerRadiusProperty =
        DependencyProperty.Register("TopRightCornerRadius", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0, OnTopRightCornerRadiusPropertyChanged));

    private static void OnTopRightCornerRadiusPropertyChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
    {
        ((UserControl)s).CornerRadius =
            new CornerRadius(((UserControl)s).CornerRadius.TopLeft, (double)e.NewValue,
                             ((UserControl)s).CornerRadius.BottomRight, ((UserControl)s).CornerRadius.BottomLeft);
    }
    #endregion

    #region BottomRightCornerRadius
    public double BottomRightCornerRadius
    {
        get { return (double)GetValue(BottomRightCornerRadiusProperty); }
        set { SetValue(BottomRightCornerRadiusProperty, value); }
    }

    // Using a DependencyProperty as the backing store for LeftCorner.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BottomRightCornerRadiusProperty =
        DependencyProperty.Register("BottomRightCornerRadius", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0, OnBottomRightCornerRadiusPropertyChanged));

    private static void OnBottomRightCornerRadiusPropertyChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
    {

        ((UserControl)s).CornerRadius =
            new CornerRadius(((ShadowPanel)s).CornerRadius.TopLeft, ((UserControl)s).CornerRadius.TopRight,
                            (double)e.NewValue, ((UserControl)s).CornerRadius.BottomLeft);
    }

    #endregion

    #region BottomLeftCornerRadius
    public double BottomLeftCornerRadius
    {
        get { return (double)GetValue(BottomLeftCornerRadiusProperty); }
        set { SetValue(BottomLeftCornerRadiusProperty, value); }
    }

    // Using a DependencyProperty as the backing store for LeftCorner.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BottomLeftCornerRadiusProperty =
        DependencyProperty.Register("BottomLeftCornerRadius", typeof(double), typeof(ShadowPanel), new PropertyMetadata(0, OnBottomLeftCornerRadiusPropertyChanged));

    private static void OnBottomLeftCornerRadiusPropertyChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
    {
        ((UserControl)s).CornerRadius =
        new CornerRadius(((UserControl)s).CornerRadius.TopLeft, ((UserControl)s).CornerRadius.TopRight,
                        ((UserControl)s).CornerRadius.BottomLeft, (double)e.NewValue);
    }
    #endregion

I know the code above is ridiculous, but I prety sure there a better way to do that

@AbdAlghaniAlbiek AbdAlghaniAlbiek added the feature request 📬 A request for new changes to improve functionality label Apr 28, 2021
@ghost
Copy link

ghost commented Apr 28, 2021

Hello, 'AbdAlghaniAlbiek! Thanks for submitting a new feature request. I've automatically added a vote 👍 reaction to help get things started. Other community members can vote to help us prioritize this feature in the future!

@Kyaa-dost
Copy link
Contributor

Kyaa-dost commented Apr 28, 2021

@AbdAlghaniAlbiek Based on the description your proposal seems unclear. Are you referring to something like this?

@michael-hawker
Copy link
Member

@AbdAlghaniAlbiek thanks for the report, we're aware of these limitations. This seems like a duplicate request of #3607 as Kyaa pointed to. We're trying to track an improved version of the pattern in #3122 for 7.1 already. Mind if we close this request as duplicate?

@AbdAlghaniAlbiek
Copy link
Author

AbdAlghaniAlbiek commented Apr 29, 2021

@michael-hawker
My problem is the same with #3607 request that we can't make a rounded corners shadow and each of us make a solution for this problem, in my solution is making completely new user control that supports shadow in easiest way without masking as #3607 solution do
In addition, this user control support TopLeftCornerRadius, TopRightCornerRadius, BottomRightCornerRadius and BottomLeftCornerRadius and these properties to control with each corner alone and this easiest way to make double animation on them (each corner), because there is no thickness animation in UWP

@Kyaa-dost Kyaa-dost added the duplicate 👥 Indicates that identical Issue or PR already exist label Apr 30, 2021
@Kyaa-dost
Copy link
Contributor

@AbdAlghaniAlbiek so this is a duplicate issue of #3607. Please feel free to include any other details of the proposal in #3607 and work on the changes if you want to by creating a PR. Thanks

@Kyaa-dost
Copy link
Contributor

Will be closing this issue due to redundancy.

@ghost
Copy link

ghost commented May 1, 2021

This issue has been marked as duplicate and has not had any activity for 1 day. It will be closed for housekeeping purposes.

@ghost ghost closed this as completed May 1, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Jun 30, 2021
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
duplicate 👥 Indicates that identical Issue or PR already exist feature request 📬 A request for new changes to improve functionality need more info 📌
Projects
None yet
Development

No branches or pull requests

3 participants