事件发生的次数越来越多

我有一个silverlight mvvm应用程序加载主视图,其中2个用户控件加载到2个ContentControls中,一个用列表框显示项目,另一个用编辑按钮。 当我单击编辑按钮时,2个新用户控件加载到ContentControls中,一个显示要编辑的数据(EditData),另一个显示保存和取消按钮(EditAction)。 当我单击“保存”按钮时,它会引发一个在单独的GlobalEvents.cs类中定义的事件,如:

public event EventHandler OnSaveButtonClicked; public void RaiseSaveButtonClicked() { this.OnSaveButtonClicked(this, EventArgs.Empty); } 

我在其他用户控件EditData中订阅它,因为我需要通过自定义EventArgs传输该编辑数据,所以我已经放入了它的ViewModel的构造函数:

 this.globalEvents.OnSaveButtonClicked += (s, e) => SaveData(); 

并在保存数据中:

 public void SaveData() { globalEvents.RaiseSaveData(EditedGuy); } 

这会引发另一个事件,将以前的用户控件加载到其ControlContent中,并在列表框中显示已编辑的数据。 多数民众赞成,但每当我点击编辑然后再次保存时,它会将事件提升两次,然后再提高3次,然后再提高4次,依此类推。 我怎样才能让它只被提升一次? 我认为这可能是因为每次我点击编辑,加载了一个用户控件的新实例,我不知道,也许订阅该事件,所以我试图粘贴

 this.globalEvents.OnSaveButtonClicked -= (s, e) => SaveData(); 

到Dispose()方法但没有成功。 我怎样才能做到这一点?

如果要从事件中取消注册,则无法使用lambdas。

 this.globalEvents.OnSaveButtonClicked += (s, e) => SaveData(); 

这将创建一个实例 – 让我们称之为实例A – 类型为EventHandler并将其添加为处理程序。

 this.globalEvents.OnSaveButtonClicked -= (s, e) => SaveData(); 

这不会从事件中删除实例A,而是创建一个新实例 – 实例B – 并尝试将其从事件中删除。

要解决此问题,请创建一个小方法或在字段中保存该匿名方法:

 class ViewModel { private EventHandler _saveButtonClickedHandler; // ... public ViewModel() { _saveButtonClickedHandler = (s, e) => SaveData(); this.globalEvents.OnSaveButtonClicked += _saveButtonClickedHandler; // ... } public void Dispose() { this.globalEvents.OnSaveButtonClicked -= _saveButtonClickedHandler; // ... } // ... } 
 this.globalEvents.OnSaveButtonClicked += (s, e) => SaveData(); 

这行被多次调用,因此每次都要添加一个新的事件处理程序。

您需要将该行移动到仅调用一次的位置或将事件处理程序更改为:

 this.globalEvents.OnSaveButtonClicked += SaveData; public void SaveData(object sender, EventArgs e) { globalEvents.RaiseSaveData(EditedGuy); this.globalEvents.OnSaveButtonClicked -= SaveData(); } 

所以你在处理之后删除了事件处理程序。 这假设下次进入编辑模式时将添加处理程序。

您可以在类中定义私有的eventhandler委托变量,并在构造函数中指定它:

 private SaveButtonClickedHandler _handler; 

在构造函数中分配处理程序:

 _handler = (s,e) => SaveData(); this.globalEvents.OnSaveButtonClicked += _handler; 

配置:

 this.globalEvents.OnSaveButtonClicked -= _handler; 

“SaveButtonClickedHandler”是伪代码/占位符,无论代理名称应该是什么。

Hasanain

你必须输入一个适当的事件处理程序方法来调用SaveData()并注册/取消注册它。 否则,您尝试取消注册另一个“新”匿名方法,而不是您注册的原始方法,因为它是匿名的,因此无法再实际访问。

 public void SaveButtonClicked(object sender, EventArgs e) { SaveData(); } this.globalEvents.OnSaveButtonClicked += SaveButtonClicked; this.globalEvents.OnSaveButtonClicked -= SaveButtonClicked;