5

I have trying to learn about EventHandler and I have to use a notification project. Here is the link of project : https://codeload.github.com/mike-eason/WPF_ToastNotifications/zip/master

All I did is changing .Net-framework from 4.5 to 4

And I faced with this error:

My class cannot be used as type parameter 'TEventArgs' in the generic type or method 'System.EventHandler'

ToastNotification Class:

 [TemplatePart(Name = "PART_DismissButton", Type = typeof(Button))]
    public class ToastNotification : ContentControl
    {
        public event EventHandler Dismissed;

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(ToastNotification));

        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set { SetValue(MessageProperty, value); }
        }

        public static readonly DependencyProperty MessageProperty =
            DependencyProperty.Register("Message", typeof(string), typeof(ToastNotification));

        public ToastTypes ToastType
        {
            get { return (ToastTypes)GetValue(ToastTypeProperty); }
            set { SetValue(ToastTypeProperty, value); }
        }

        public static readonly DependencyProperty ToastTypeProperty =
            DependencyProperty.Register("ToastType", typeof(ToastTypes), typeof(ToastNotification), new PropertyMetadata(new PropertyChangedCallback(OnToastTypeChanged)));

        private static void OnToastTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ToastNotification toast = (ToastNotification)d;

            toast.RefreshBackgroundColour();
        }

        private void RefreshBackgroundColour()
        {
            switch (ToastType)
            {
                case ToastTypes.Success:
                    Background = ColourSuccess;
                    break;
                case ToastTypes.Error:
                    Background = ColourDanger;
                    break;
                case ToastTypes.Info:
                    Background = ColourInfo;
                    break;
                case ToastTypes.Warning:
                    Background = ColourWarning;
                    break;
            }
        }

        public bool IsPersistent
        {
            get { return (bool)GetValue(IsPersistentProperty); }
            set { SetValue(IsPersistentProperty, value); }
        }

        public static readonly DependencyProperty IsPersistentProperty =
            DependencyProperty.Register("IsPersistent", typeof(bool), typeof(ToastNotification));

        public double FontSizeTitle
        {
            get { return (double)GetValue(FontSizeTitleProperty); }
            set { SetValue(FontSizeTitleProperty, value); }
        }

        public static readonly DependencyProperty FontSizeTitleProperty =
            DependencyProperty.Register("FontSizeTitle", typeof(double), typeof(ToastNotification));

        public Brush ColourSuccess
        {
            get { return (Brush)GetValue(ColourSuccessProperty); }
            set { SetValue(ColourSuccessProperty, value); }
        }

        public static readonly DependencyProperty ColourSuccessProperty =
            DependencyProperty.Register("ColourSuccess", typeof(Brush), typeof(ToastNotification));

        public Brush ColourDanger
        {
            get { return (Brush)GetValue(ColourDangerProperty); }
            set { SetValue(ColourDangerProperty, value); }
        }

        public static readonly DependencyProperty ColourDangerProperty =
            DependencyProperty.Register("ColourDanger", typeof(Brush), typeof(ToastNotification));

        public Brush ColourInfo
        {
            get { return (Brush)GetValue(ColourInfoProperty); }
            set { SetValue(ColourInfoProperty, value); }
        }

        public static readonly DependencyProperty ColourInfoProperty =
            DependencyProperty.Register("ColourInfo", typeof(Brush), typeof(ToastNotification));

        public Brush ColourWarning
        {
            get { return (Brush)GetValue(ColourWarningProperty); }
            set { SetValue(ColourWarningProperty, value); }
        }

        public static readonly DependencyProperty ColourWarningProperty =
            DependencyProperty.Register("ColourWarning", typeof(Brush), typeof(ToastNotification));

        static ToastNotification()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ToastNotification), new FrameworkPropertyMetadata(typeof(ToastNotification)));
        }

        public ToastNotification()
        {
            this.Loaded += ToastNotification_Loaded;
        }

        private void ToastNotification_Loaded(object sender, RoutedEventArgs e)
        {
            Storyboard sb = this.FindResource("ToastScaleInStoryboard") as Storyboard;
            Storyboard.SetTarget(sb, this);
            sb.Begin();
        }

        public override void OnApplyTemplate()
        {
            ButtonBase PART_DismissButton = this.GetTemplateChild("PART_DismissButton") as ButtonBase;

            if (PART_DismissButton != null)
                PART_DismissButton.Click += OnDismissed;

            base.OnApplyTemplate();

            RefreshBackgroundColour();
        }

        protected void OnDismissed(object sender, RoutedEventArgs e)
        {
            var eh = Dismissed;

            if (eh != null)
                eh(this, EventArgs.Empty);
        }
    }

Toast Class:

  internal class Toast
    {
        public event EventHandler<ToastNotification> ToastClosing;

        private DispatcherTimer _Timer;
        private ToastNotification _Notification;

        public Toast(ToastNotification notification)
        {
            _Notification = notification;

            _Notification.Dismissed += Notification_Dismissed;
        }

        private void Notification_Dismissed(object sender, EventArgs e)
        {
            OnToastClosing();
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            //Stop and close the window.
            _Timer.Stop();

            OnToastClosing();
        }

        public void Show(TimeSpan displayTime)
        {
            //Only start the timer if the notification is not persistent.
            if (!_Notification.IsPersistent)
            {
                //Set up the timer
                _Timer = new DispatcherTimer();
                _Timer.Interval = displayTime;
                _Timer.Tick += Timer_Tick;

                //Start the timer
                _Timer.Start();
            }
        }

        protected void OnToastClosing()
        {
            //Unsubscribe from the on dismiss event first (to avoid memory leaks)
            _Notification.Dismissed -= Notification_Dismissed;

            var eh = ToastClosing;

            if (eh != null)
                eh(this, _Notification);
        }
    }
arna
  • 53
  • 5

2 Answers2

3

System.EventHandler<T> delegate was changed in .NET 4.5. Before 4.5 it has the following signature:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e)
    where TEventArgs : EventArgs;

Starting with .NET 4.5 it has another definition:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

Note that where ... part has been removed. So before .NET 4.5 the type you use for event handler argument should inherit from EventArgs. Your ToastNotification does not inherit from that class, so cannot be used, hence your compiler error. When project targets .NET 4.5+ - you can use any type there so it compiles fine.

You can change your ToastClosing to

public event Action<object, ToastNotification> ToastClosing;

and it will compile just fine.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • Thanks, works fine, just ToastClosing not working, and I couldn't close toast. – arna Nov 16 '17 at 08:09
  • @arna maybe you click on green "Test Toast" inside window itself? Because you need to click on buttons below ("success" "error" etc) which will show real toast. That one will close just fine when you click X button. – Evk Nov 16 '17 at 08:13
  • sorry,I try but close button not works, should change it to: public delegate void EventHandler(object sender, ToastNotification e) where ToastNotification : EventArgs; public event Action ToastClosing; – arna Nov 16 '17 at 10:30
  • @arna I downloaded your project, changed to .NET 4.0, changed `public event EventHandler ToastClosing;` to `public event Action ToastClosing;` without chaning anything else, then run and closing works fine. – Evk Nov 16 '17 at 10:32
0
public event Action<object, ToastNotification> ToastClosing;

I think the recommendation is to inherit 'EventArgs'.

public class MyEventArgs : EventArgs
{ }

public event EventHandler<MyEventArgs> MyEvent;
Jaeho Lee
  • 42
  • 5