2

I have been trying to create a notification window, but I'm struggling to figure out why this opacity shift is not happening when I run it. Instead the window will hold for a second then close without any visible changes. All my other attempts via other methods have failed too, so it must be some property I am missing. Thanks for any help!

    public void RunForm(string error, MessageBoxIcon icon, int duration)
    {
        lblMessage.Text = error;
        Icon i = ToSystemIcon(icon);
        if (i != null)
        {
            BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(i.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            imgIcon.Source = bs;
        }
        this.WindowStartupLocation = WindowStartupLocation.Manual;
        this.Show();
        this.Left = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Right - this.RestoreBounds.Width - 20;
        this.Top = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Bottom - this.RestoreBounds.Height - 20;
        while (this.Opacity > 0)
        {
            this.Opacity -= 0.05;
            Thread.Sleep(50);
        }
        this.Close();
    }


<Window Width="225" Height="140" VerticalContentAlignment="Center" HorizontalAlignment="Center" ShowActivated="True" ShowInTaskbar="False"
ResizeMode="NoResize" Grid.IsSharedSizeScope="False" SizeToContent="Height" WindowStyle="None" BorderBrush="Gray" 
BorderThickness="1.5" Background="White" Topmost="True" AllowsTransparency="True" Opacity="1">
<Grid Height="Auto" Name="grdNotificationBox" >
    <Image Margin="12,12,0,0" Name="imgIcon" Stretch="Fill" HorizontalAlignment="Left" Width="32" Height="29" VerticalAlignment="Top" />
    <TextBlock Name="lblMessage" TextWrapping="Wrap" Margin="57,11,17,11"></TextBlock>
</Grid>

Tim
  • 2,968
  • 5
  • 29
  • 55

2 Answers2

2

This can't work: The complete WPF handling is done in one single thread (technically two but not important). you change the opacity and directly let the ui thread sleep, change it again and send it back to sleep. The ui thread never got any time to process what you did. Even removing the sleep would not help, because than it would be much to fast, and the ui thread could not handle any requests aswell. Its important to understand that your code and WPFs handling is done in the same thread, the longer you need, the less time WPF got and vice versa.

To solve it you need to use animations. They are exactly for these kind of thing. Checkout this thread.

Community
  • 1
  • 1
dowhilefor
  • 10,971
  • 3
  • 28
  • 45
  • Thanks. I'm having trouble with the single threading of WCF alot today. I've ended up going with ShowDialog() and animations. – Tim May 25 '12 at 14:17
1

You are basically blocking the UI thread to update in your while loop. Do this using a timer or use Background Worker Thread more appropriately.

Edit: As dowhilefor indicated that you can use WPF Animations for this purpose. This article here discuss this in detail.

DoubleAnimation da = new DoubleAnimation();
da.From = 1;
da.To = 0;
da.Duration = new Duration(TimeSpan.FromSeconds(2));
da.AutoReverse = true;
da.RepeatBehavior = RepeatBehavior.Forever;
rectangle1.BeginAnimation(OpacityProperty, da);
ABH
  • 3,391
  • 23
  • 26