C# 尝试在WPF中激发事件时,EventHandler为null 问题
我在类C# 尝试在WPF中激发事件时,EventHandler为null 问题,c#,wpf,event-handling,C#,Wpf,Event Handling,我在类LoginVM中创建了一个事件,如下所示: public class LoginVM : INotifyPropertyChanged { public event EventHandler<string> PasswordSet; } 正如您可能知道的那样,我正试图从ViewModel到视图触发事件,但每次我从ViewModel触发事件时,密码集都是空的,并且有错误。如果没有事件的侦听器,则事件是空的 private void RaisePasswordSet(St
LoginVM
中创建了一个事件,如下所示:
public class LoginVM : INotifyPropertyChanged
{
public event EventHandler<string> PasswordSet;
}
正如您可能知道的那样,我正试图从
ViewModel
到视图
触发事件,但每次我从ViewModel
触发事件时,密码集
都是空的,并且有错误。如果没有事件的侦听器,则事件是空的
private void RaisePasswordSet(String pass) {
YourEventArgs args = new YourEventArgs(pass);
if(PasswordSet != null) PasswordSet(this, args);
}
您的问题是,当您尝试引发事件时,没有人侦听它,,当事件没有侦听器时,事件为空
private void RaisePasswordSet(String pass) {
YourEventArgs args = new YourEventArgs(pass);
if(PasswordSet != null) PasswordSet(this, args);
}
您的问题是,当您尝试引发事件时,没有人收听它,最好像您那样初始化
LoginVM
的构造函数中的密码。这时应该进行初始化。通常,您会设置一个属性,XAML中的绑定将负责更新控件。虚拟机上不需要事件。但是这是一个密码框,所以您不能绑定它,您编写的事件是正确的
但在您的实现中,这就给您留下了一系列事件:
C#
最好像您那样初始化LoginVM
的构造函数中的密码。这时应该进行初始化。通常,您会设置一个属性,XAML中的绑定将负责更新控件。虚拟机上不需要事件。但是这是一个密码框,所以您不能绑定它,您编写的事件是正确的
但在您的实现中,这就给您留下了一系列事件:
创建虚拟机
VM在其构造函数中引发PasswordSet,而不检查是否存在任何处理程序
视图将VM分配给DataContext
视图将处理程序添加到PasswordSet事件
在第2步,您会得到一个异常,因为您没有检查处理程序
这是你要做的
在VM或任何地方,始终使用此模式引发事件:
C#您是否也在XAML中创建viewmodel?或者其他地方?我不明白你的登录码。你似乎在一个活动之外提出这个事件。您的问题可能是引发事件的LoginVM对象不是您所使用的对象。向我们展示活动是如何进行的happens@EdPlunkett不,仅针对DataContextLoginVM是否在其构造函数中调用PopulateLatestServer(),或者在其构造函数或某些初始值设定项可能调用的任何代码中调用?您是否也在XAML中创建viewmodel?或者其他地方?我不明白你的登录码。你似乎在一个活动之外提出这个事件。您的问题可能是引发事件的LoginVM对象不是您所使用的对象。向我们展示活动是如何进行的happens@EdPlunkett不,仅针对DataContextDoes LoginVM在其构造函数中调用PopulateLatestServer(),或者在其构造函数或某些初始值设定项可能调用的任何代码中调用PopulateLatestServer()?但问题是它将始终为空,但我需要在那时触发该事件。@BenClarke,我认为您调用PopulateLatestServer()方法,然后再对其进行任何订阅。这可能是原因,处理程序总是null@BenClarke您有两种解决方案:使用事件,并且必须确保在订阅之前初始化值,因为初始值不会通知您,或者在XAML a属性中将ViewModel绑定到您的应用程序Control@nkoniishvt我设法把它修好了。我无法绑定该属性,因为它是密码箱。我只是没有在构造函数中调用该方法。但问题是它将始终为null,但我需要在该时间触发该事件。@BenClarke,我想您在订阅它之前调用PopulateLatestServer()方法。这可能是原因,处理程序总是null@BenClarke您有两种解决方案:使用事件,并且必须确保在订阅之前初始化值,因为初始值不会通知您,或者在XAML a属性中将ViewModel绑定到您的应用程序Control@nkoniishvt我设法把它修好了。我无法绑定该属性,因为它是密码箱。我还没有在构造函数中调用该方法。
private void RaisePasswordSet(String pass) {
YourEventArgs args = new YourEventArgs(pass);
if(PasswordSet != null) PasswordSet(this, args);
}
protected void OnPasswordSet(String e)
{
var handler = PasswordSet;
if (handler != null)
{
handler(this, e);
}
}
protected void OnPasswordSet(String e) => PasswordSet?.Invoke(this, e);
private void PopulateLatestServer()
{
try
{
string SERVER_ID = Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\PODIA", "LATESTSERVER", null).ToString();
BDO_SERVERS latestserver = SavedServers.Where(a => a.Server_ID == SERVER_ID).FirstOrDefault();
setServerURL(latestserver.ServerURL, false);
Username = latestserver.Username;
OnPasswordSet(latestserver.Password);
}
catch (Exception)
{
Global.WriteLog("Could not find last logged in server.", EventLogEntryType.Warning);
}
}
public partial class LoginV : MetroWindow
{
public LoginV()
{
InitializeComponent();
LoginVM _loginVM = new LoginVM();
this.DataContext = _loginVM;
_loginVM.PasswordSet += new EventHandler<string> (_loginVM_PasswordSet);
UpdatePassword();
}
protected void UpdatePassword()
{
passwordBox.Password = e;
}
private void _loginVM_PasswordSet(object sender, string e)
{
UpdatePassword();
}
public class LoginVM : INotifyPropertyChanged
{
public LoginVM(EventHandler<string> passwordSetHandler)
{
if (passwordSetHandler != null)
{
PasswordSet += passwordSetHandler;
}
PopulateLatestServer();
}
// If the consumer doesn't want to handle it right way, don't force the issue.
public LoginVM()
{
PopulateLatestServer();
}
public class LoginVM : INotifyPropertyChanged
{
private event EventHandler<string> _passwordSet;
public event EventHandler<string> PasswordSet
{
add
{
_passwordSet += value;
// ...or else save latestServer in a private field, so here you can call
// OnPasswordSet(_latestServer.Password) -- but since it's a password,
// best not to keep it hanging around.
PopulateLatestServer();
}
remove { _passwordSet -= value; }
}