Мой класс нельзя использовать в качестве параметра типа «TEventArgs» в универсальном типе или методе «System.EventHandler‹TEventArgs›» в .Net 4

Я пытаюсь узнать о EventHandler, и мне нужно использовать проект уведомлений. Вот ссылка на проект: https://codeload.github.com/mike-eason/WPF_ToastNotifications/zip/master

Все, что я сделал, это изменил .Net-framework с 4.5 на 4.

И я столкнулся с этой ошибкой:

Мой класс нельзя использовать в качестве параметра типа «TEventArgs» в универсальном типе или методе «System.EventHandler».

Класс ToastNotification:

 [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);
        }
    }

Тост Класс:

  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);
        }
    }

person arna    schedule 16.11.2017    source источник
comment
Какая линия? Если это ошибка времени выполнения, опубликуйте также трассировку стека.   -  person Stefan    schedule 16.11.2017
comment
Публичное событие @Stefan EventHandler‹ToastNotification› ToastClosing;   -  person arna    schedule 16.11.2017


Ответы (2)


System.EventHandler<T> делегат был изменен в .NET 4.5. До версии 4.5 он имел следующую подпись. :

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

Начиная с .NET 4.5, он имеет другое определение:

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

Обратите внимание, что часть where ... была удалена. Поэтому до .NET 4.5 тип, который вы используете для аргумента обработчика событий, должен наследоваться от EventArgs. Ваш ToastNotification не наследуется от этого класса, поэтому его нельзя использовать, следовательно, ваша ошибка компилятора. Когда проект нацелен на .NET 4.5+, вы можете использовать любой тип, чтобы он компилировался нормально.

Вы можете изменить свой ToastClosing на

public event Action<object, ToastNotification> ToastClosing;

и он будет компилироваться просто отлично.

person Evk    schedule 16.11.2017
comment
Спасибо, работает нормально, просто ToastClosing не работает, и я не могу закрыть тост. - person arna; 16.11.2017
comment
@arna, может быть, вы нажмете на зеленый тестовый тост внутри самого окна? Потому что вам нужно нажать на кнопки ниже (ошибка успеха и т. д.), которые будут показывать настоящий тост. Тот закроется просто отлично, когда вы нажмете кнопку X. - person Evk; 16.11.2017
comment
извините, я пытаюсь, но кнопка закрытия не работает, следует изменить ее на: открытый делегат void EventHandler‹ToastNotification›(отправитель объекта, ToastNotification e) где ToastNotification : EventArgs; публичное событие Action‹object, ToastNotification› ToastClosing; - person arna; 16.11.2017
comment
@arna Я загрузил ваш проект, перешел на .NET 4.0, изменил public event EventHandler<ToastNotification> ToastClosing; на public event Action<object, ToastNotification> ToastClosing;, ничего не меняя, затем запустил и закрытие работает нормально. - person Evk; 16.11.2017

public event Action<object, ToastNotification> ToastClosing;

Я думаю, что рекомендуется наследовать EventArgs.

public class MyEventArgs : EventArgs
{ }

public event EventHandler<MyEventArgs> MyEvent;
person Jaeho Lee    schedule 16.11.2017