C# WPF) DropShadowEffect is sometimes missing when dynamically adding a control

1.2k views Asked by At

enter image description here

foreach (DataRow dr in dt.Rows)
{
    Rectangle rectangle_timeline = new Rectangle();
    rectangle_timeline.Height = 19;
    rectangle_timeline.Cursor = Cursors.Hand;

    rectangle_timeline.Effect = new DropShadowEffect
    {
        Color = new Color { A = 255, R = 0, G = 0, B = 0 },
        Direction = 315,
        ShadowDepth = 5,
        Opacity = 1
    };

    Grid_Timeline.Children.Add(rectangle_timeline);
}

I dynamically add a Rectangle with above simple code as shown image.

However, sometimes, randomly, there're rectangles without DropShadowEffect like yellow rectangles and 1 blue rectangle at the lowest.

As you see the code, if a rectangle is added, the code for DropShadowEffect should have to be worked.

I'm wondering why this is happening.

Thank you !

XAML code added-

<Grid x:Name="Grid_Timeline" ScrollViewer.VerticalScrollBarVisibility="Auto" UseLayoutRounding="True" Width="1159" HorizontalAlignment="Left" VerticalAlignment="Top" SnapsToDevicePixels="True">
</Grid>

Minimal code to re-produce is added-

private void Window_Loaded(object sender, RoutedEventArgs e)
{
        int count_each_category = 0;
        string current_therapeutic_category = String.Empty;

        foreach (DataRow dr_test in dt.Rows)
        {
            if (dr_test != null)
            {
                if (current_category == String.Empty)
                {
                    count_each_category++;

                    current_category = dr_test["category"].ToString();
                }
                else
                {
                    if (current_category == dr_test["category"].ToString())
                    {
                        // empty
                    }
                    else
                    {
                        count_each_category++;

                        current_category = dr_test["category"].ToString();
                    }
                }

                Rectangle rectangle_test = new Rectangle();

                rectangle_test.HorizontalAlignment = HorizontalAlignment.Left;
                rectangle_test.VerticalAlignment = VerticalAlignment.Top;

                rectangle_test.Margin = new Thickness(119 + (((Convert.ToDateTime(dr_test["date"]) - DateTime.Today.AddYears(-10)).TotalDays) * 0.27), count_each_category * 50, 0, 0);

                rectangle_test.Width = 0.27 * Convert.ToInt32(dr_test["howlong"]);
                rectangle_test.Height = 19;

                rectangle_test.Effect = new DropShadowEffect
                {
                    Color = new Color { A = 255, R = 0, G = 0, B = 0 },
                    Direction = 315,
                    ShadowDepth = 5,
                    Opacity = 1
                };

                rectangle_test.Fill = Brushes.LightGreen;

                Grid_Timeline.Children.Add(rectangle_test);
            }
        }
}

XAML code of WPF Window

<Window x:Class="OperationSWdummy.Green_Timeline"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:OperationSWdummy"
    mc:Ignorable="d"
    Title="Green_Timeline" Width="1165" Background="White" ResizeMode="CanMinimize" ScrollViewer.VerticalScrollBarVisibility="Auto" UseLayoutRounding="True" SnapsToDevicePixels="True" Loaded="Window_Loaded">
<Grid x:Name="Grid_Timeline" ScrollViewer.VerticalScrollBarVisibility="Auto" UseLayoutRounding="True" Width="1159" HorizontalAlignment="Left" VerticalAlignment="Top" SnapsToDevicePixels="True">
</Grid>
</Window>

Raw data of dt (DataTable)

date        datetime

category    NVARCHAR

howlong     int

   date     category howlong 
2015-01-25    HHH      60 
2014-04-03    AAA      60 
2015-01-25    DDD      60 
2014-04-03    UUU      60 
2015-01-25    CCC      60 
2015-11-07    PPP      30 
2015-01-25    TTT      60 
2015-11-07    MMM      30 
2015-02-22    MMM      30 
2015-11-07    VVV       8 

Result of above minimal code Result of above minimal code

Another minimal code to create rectangles randomly-

for (int k = 0; k < 191; k++)
        {
            Rectangle rec_test = new Rectangle();
            rec_test.Margin = new Thickness(random_margin.Next(100, 1000), 29 * (k % 10), 0, 0);
            rec_test.Width = random_width.Next(10, 40);
            rec_test.HorizontalAlignment = HorizontalAlignment.Left;
            rec_test.VerticalAlignment = VerticalAlignment.Top;
            rec_test.Height = 14;
            rec_test.Cursor = Cursors.Hand;
            rec_test.Effect = new DropShadowEffect
            {
                Color = new Color { A = 255, R = 0, G = 0, B = 0 },
                Direction = 315,
                ShadowDepth = 5,
                Opacity = 1
            };

            rec_test.Fill = Brushes.Green;

            Grid_Timeline.Children.Add(rec_test);
        }
2

There are 2 answers

2
l33t On

Could be a driver problem with your graphics hardware. Try disabling hardware acceleration and see if it helps.

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
         RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
    }
}

In general I advise against using the DropShadowEffect as it will have a significantly negative impact on rendering performance.

2
Eriawan Kusumawardhono On

Have you tried to use Canvas to place your rectangles?

Having Canvas to place your shapes such as rectangles, circles, or even graphical paths with random locations is better than placing on fixed layout container such as Grid or StackPanel.

It is quite known that if you just placed shapes with effects such as DropShadow on fixed layout (with arbitrary X,Y locations) such as Grid and StackPanel, your shapes may be clipped. Because the shapes edges will always be checked for pixel boundaries at render time, and often this is caused by overlapped rendering calculations when it tries to recalculate edges of fixed layout controls.