事件和委托的基础。使用它的 class 中来自 INotifyPropertyChanged 的 PropertyChange 事件的事件订阅行
Basic of Event and Delegate. Event Subscribe line of PropertyChange Event from INotifyPropertyChanged in the class using it
嗨,我从 https://www.youtube.com/watch?v=jQgwEsJISy0&t=1230s 那里了解到了事件和委托。在此他说要举办活动,我们需要三步
- 定义委托
- 根据该委托定义一个事件
- 引发该事件
我跟随他并在控制台中制作了应用程序,但由于我在 WPF 中工作,所以我将 post 我在 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...");
}
}
}
所以我的知识是
An Event has to be Subscribed in order to execute using += sign.
但是根据我的知识,当我使用来自 INotifyPropertyChange 的 属性change 事件时,不需要 += 符号。而且 st运行ge 似乎 +=(订阅事件)是动态完成的,但是因为如果我首先初始化 属性 (在我的例子中,如果我初始化 FirstName 的值,则在下面的代码中显示=Jeff and LastName=Buckley) 然后它触发我代码中的 else 部分并在开头显示消息 "There is no Subscriber to which MyOnPropertyChanged function can call " 。我相信这是因为事件订阅者是空的(即没有像我期望的那样 += 事件分配语句)但是后来一旦 window 被加载它似乎有事件订阅者虽然我没有这样做在代码上。下面是我的代码实现 属性changed.
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;
}
}
}
所以我的困惑是在第一个代码中我必须使用 += 分配事件,但在第二个代码中它可以在不执行 += 的情况下工作。我无法弄清楚不使用 += 作为事件的第二个代码 运行 如何需要使用 += 链接到订阅者。
我尝试在线阅读并查看视频以获取解释,但不明白我为什么要在这里提问。到目前为止,我从这里学到了很多东西,谢谢你,也谢谢你花时间阅读这个问题,在你的帮助下我可以掌握这个问题。
简答。
第一个代码示例在 MainWindow.ctor()
内订阅 EventDefinedInInterface
并在 PublisherMethodForConnection
内引发它。
第二个代码示例根本不订阅 PropertyChanged
。它只是在 MyOnPropertyChanged_PublisherMethod
.
中引发此事件
长答案。
通常,事件旨在通知外部 订阅者有关对象内部发生的一些变化(属性 已更改其值,视频已编码,等)。
虽然技术上您可以订阅自己的活动,但这通常没有意义。例如,如果 MainWindow
实例想要做某事,当 LastName
被更改时,它可以在 属性 setter 或 MyOnPropertyChanged_PublisherMethod
方法中处理。无需订阅活动。
所以,当你想订阅某个对象的事件时,你必须使用+=
语法来添加你的事件处理程序。当您想引发一个事件时,您通常会调用私有或受保护的方法来执行此操作,但是 这不是 事件 handling/subscription.
以下是在 C# 中实现事件之前要阅读的三个链接:
我希望通过上面提供的描述和下面的代码,其他人也可以从中受益
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 of for running in 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>
嗨,我从 https://www.youtube.com/watch?v=jQgwEsJISy0&t=1230s 那里了解到了事件和委托。在此他说要举办活动,我们需要三步
- 定义委托
- 根据该委托定义一个事件
- 引发该事件
我跟随他并在控制台中制作了应用程序,但由于我在 WPF 中工作,所以我将 post 我在 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...");
}
}
}
所以我的知识是
An Event has to be Subscribed in order to execute using += sign.
但是根据我的知识,当我使用来自 INotifyPropertyChange 的 属性change 事件时,不需要 += 符号。而且 st运行ge 似乎 +=(订阅事件)是动态完成的,但是因为如果我首先初始化 属性 (在我的例子中,如果我初始化 FirstName 的值,则在下面的代码中显示=Jeff and LastName=Buckley) 然后它触发我代码中的 else 部分并在开头显示消息 "There is no Subscriber to which MyOnPropertyChanged function can call " 。我相信这是因为事件订阅者是空的(即没有像我期望的那样 += 事件分配语句)但是后来一旦 window 被加载它似乎有事件订阅者虽然我没有这样做在代码上。下面是我的代码实现 属性changed.
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;
}
}
}
所以我的困惑是在第一个代码中我必须使用 += 分配事件,但在第二个代码中它可以在不执行 += 的情况下工作。我无法弄清楚不使用 += 作为事件的第二个代码 运行 如何需要使用 += 链接到订阅者。
我尝试在线阅读并查看视频以获取解释,但不明白我为什么要在这里提问。到目前为止,我从这里学到了很多东西,谢谢你,也谢谢你花时间阅读这个问题,在你的帮助下我可以掌握这个问题。
简答。
第一个代码示例在 MainWindow.ctor()
内订阅 EventDefinedInInterface
并在 PublisherMethodForConnection
内引发它。
第二个代码示例根本不订阅 PropertyChanged
。它只是在 MyOnPropertyChanged_PublisherMethod
.
长答案。
通常,事件旨在通知外部 订阅者有关对象内部发生的一些变化(属性 已更改其值,视频已编码,等)。
虽然技术上您可以订阅自己的活动,但这通常没有意义。例如,如果 MainWindow
实例想要做某事,当 LastName
被更改时,它可以在 属性 setter 或 MyOnPropertyChanged_PublisherMethod
方法中处理。无需订阅活动。
所以,当你想订阅某个对象的事件时,你必须使用+=
语法来添加你的事件处理程序。当您想引发一个事件时,您通常会调用私有或受保护的方法来执行此操作,但是 这不是 事件 handling/subscription.
以下是在 C# 中实现事件之前要阅读的三个链接:
我希望通过上面提供的描述和下面的代码,其他人也可以从中受益
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 of for running in 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>