Основы событий и делегатов.Строка подписки на событие PropertyChange Event из INotifyPropertyChanged в классе, использующем его - PullRequest
0 голосов
/ 26 ноября 2018

Привет, я узнал о событии и делегате от https://www.youtube.com/watch?v=jQgwEsJISy0&t=1230s. В этом он говорит, что для создания события нам нужно три шага

  1. Определение делегата
  2. Определение событияосновываясь на этом делегате
  3. Поднять это событие

Я последовал за ним и создал приложение в консоли, но поскольку я работаю в WPF, я опубликую здесь код, который я использовал в WPF, икод, как показано ниже:

namespace WpfApp5
{
    public delegate void step1DelegateDefinition(); // Step-1: Define a delegate

    public interface INotifyOnVideoEncoded
    {
        event step1DelegateDefinition EventDefinedInInterface;// Step-2a:  Define an event based on that delegate
    }

    public partial class MainWindow : Window, INotifyOnVideoEncoded
    {
        public event step1DelegateDefinition EventDefinedInInterface; //Step-2b:  Define an event based on that delegate

        public MainWindow()
        {
           InitializeComponent();
           this.DataContext = this;
           ObservableCollection<string> NotificationText = new ObservableCollection<string>();
            EventDefinedInInterface += SubscriberMethodForConection;// A method corresponding to delegate is subscribed for that event 
            Encode();
        }

        public void Encode()
        {
            MessageBox.Show("Encoding Video...");
            Thread.Sleep(3000);
            PublisherMethodForConnection(); //Step-3: Raise an event
        }

        public void PublisherMethodForConnection()
        {
            if (EventDefinedInInterface != null)
                EventDefinedInInterface();
            else
                MessageBox.Show("No Subscriber");
        }

        public void SubscriberMethodForConection()
        {
            MessageBox.Show("MailService: Sending an email...");
        }
    }       
}

Итак, насколько мне известно,

Событие должно быть подписано для выполнения с использованием знака + =.

Но в отличие от моих знаний, когда я использую событие changechange из INotifyPropertyChange, знак + = не нужен.и более того, странно, что + = (подписка на событие) выполняется динамически, но потому что, если я сначала инициализирую свойство (в моем случае, представленном в коде ниже, если я инициализирую значение FirstName = Jeff и LastName = Buckley), то оно срабатываетчасть else в моем коде и показывает сообщение «Нет подписчика, которому функция MyOnPropertyChanged может вызвать» в начале.Я полагаю, что это потому, что подписчик на событие является нулевым (то есть нет оператора + = +, присваивающего событие, как я ожидал), но позже, когда окно загружено, кажется, что есть подписчик на событие, хотя я не делал этого в коде.Ниже приведен мой код Реализация свойства изменена.

namespace UnderstandingINotifyPropertyChanged
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _FirstName;
        private string _FullName;
        private string _LastName;

        public string FirstName
        {
            get { return _FirstName; }
            set
            {
                if (_FirstName != value)
                {
                    _FirstName = value;
                    MyOnPropertyChanged_PublisherMethod("FirstName");
                    MyOnPropertyChanged_PublisherMethod("FullName");
                }
            }
        }
        public string LastName
        {
            get { return _LastName; }
            set
            {
                if (_LastName != value)
                {
                    _LastName = value;
                    MyOnPropertyChanged_PublisherMethod("Lastname");
                    MyOnPropertyChanged_PublisherMethod("FullName");
                }
            }
        }
        public string FullName
        {
            get { return _FullName = _FirstName + " " + _LastName; }

        }

        private void MyOnPropertyChanged_PublisherMethod(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
            else
                MessageBox.Show("There is no Subscriber to which MyOnPropertyChanged function can call ");
        }

        public MainWindow()
        {
            InitializeComponent();
            FirstName = "Jeff";
            LastName = "Buckley";
            this.DataContext = this;
           
        }
    }
}

Так что моя путаница в первом коде, я должен назначить событие, используя + =, но во втором коде это работает без + +.Я не могу понять, как второй код запускался без использования + =, поскольку событие должно быть связано с использованием + = к подписчику.

Я пытался читать онлайн и смотреть видео для объяснения, но не мог понять, по какой причине я спрашиваю здесь.До сих пор я многому научился здесь, спасибо вам за это и спасибо, что вы нашли время, чтобы прочитать этот вопрос, я могу понять это с вашей помощью.

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Надеюсь, с приведенным выше описанием и игрой с кодом ниже, другие также могут воспользоваться

MainWindow.xaml.cs

namespace UnderstandingINotifyPropertyChanged
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        Class1 Class1Object = new Class1();
        private string _FirstName;
        private string _FullName;
        private string _LastName;

        public string FirstName
        {
            get { return _FirstName; }
            set
            {
                if (_FirstName != value)
                {
                    _FirstName = value;
                    RaisePropertyChanged("FirstName");
                    RaisePropertyChanged("FullName");
                }
            }
        }
        public string LastName
        {
            get { return _LastName; }
            set
            {
                if (_LastName != value)
                {
                    _LastName = value;
                    RaisePropertyChanged("Lastname");
                    RaisePropertyChanged("FullName");
                }
            }
        }
        public string FullName
        {
            get { return _FullName = _FirstName + " " + _LastName; }

        }

        protected virtual void RaisePropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));           
        }
        Class1 ObjectOfClass1 = new Class1();

        public MainWindow()
        {
            InitializeComponent();
            FirstName = "Jeff";
            LastName = "Buckley";
            this.DataContext = this;
            PropertyChanged += ObjectOfClass1.MethodToBeTracked;
        }
    }

    public class Class1
    {
        public void MethodToBeTracked(object sender, PropertyChangedEventArgs e)
        {
            MessageBox.Show("propertychanged event fired due to change in property " + e);
        }
    }
}

XAML для работы в WPF

<Window x:Class="UnderstandingINotifyPropertyChanged.MainWindow"
        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:UnderstandingINotifyPropertyChanged"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="400">
    <StackPanel HorizontalAlignment="Center" Margin="0,30,0,0">
        <StackPanel Orientation="Horizontal" Margin="10">
            <Label Content="First Name : "  />
            <!--<TextBox Width="200" VerticalContentAlignment="Center" Text="{Binding Path=FirstName,Mode=TwoWay,  UpdateSourceTrigger=PropertyChanged}"/>-->
            <TextBox Width="200" VerticalContentAlignment="Center" Text="{Binding Path=FirstName,Mode=TwoWay}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" Margin="10">
                <Label Content="Last Name : "  />
                <!--<TextBox Width="200" VerticalContentAlignment="Center" Text="{Binding LastName,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>-->
                <TextBox Width="200" VerticalContentAlignment="Center" Text="{Binding LastName,Mode=TwoWay}"/>
            </StackPanel>
        <StackPanel Orientation="Horizontal" Margin="10">
            <Label Content="Full Name : "  />
            <!--<TextBox Width="200" VerticalContentAlignment="Center" Text="{Binding Path=FullName,Mode=TwoWay,  UpdateSourceTrigger=PropertyChanged}"/>-->
            <Label Width="200" VerticalContentAlignment="Center" Content="{Binding Path=FullName,Mode=OneWay}"/>
        </StackPanel>
    </StackPanel>
</Window>
0 голосов
/ 26 ноября 2018

Короткий ответ.

Первый пример кода подписывается EventDefinedInInterface внутри MainWindow.ctor() и повышает его внутри PublisherMethodForConnection.

Второй пример кода вообще не подписывается PropertyChanged.Это просто вызывает это событие внутри MyOnPropertyChanged_PublisherMethod.

Длинный ответ.

Обычно события предназначены для уведомления внешнего подписчика (ей) онекоторые изменения произошли внутри объекта (свойство изменило свое значение, видео было закодировано и т. д.).

Хотя технически вы можете подписаться на собственное событие, обычно это не делаетсмысл.Например, если MainWindow экземпляр хочет что-то сделать, когда LastName был изменен, он может обработать это внутри метода установки свойств или MyOnPropertyChanged_PublisherMethod метода.Нет необходимости в подписке на события.

Итак, если вы хотите подписать событие какого-либо объекта, вы должны использовать синтаксис +=, чтобы добавить свой обработчик событий,Когда вы хотите вызвать событие, вы обычно вызываете закрытый или защищенный метод, который делает это, но это не обработка события / подписка.

Ниже приведены три ссылки для чтения перед реализацией событияв C #:

...