我有一个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()方法但没有成功。我怎样才能做到这一点?
答案 0 :(得分:7)
如果要取消注册事件,则无法使用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;
// ...
}
// ...
}
答案 1 :(得分:2)
this.globalEvents.OnSaveButtonClicked += (s, e) => SaveData();
此行被多次调用,因此您每次都要添加一个新的事件处理程序。
您需要将该行移动到仅调用一次的位置或将事件处理程序更改为:
this.globalEvents.OnSaveButtonClicked += SaveData;
public void SaveData(object sender, EventArgs e)
{
globalEvents.RaiseSaveData(EditedGuy);
this.globalEvents.OnSaveButtonClicked -= SaveData();
}
所以你在处理之后删除了事件处理程序。这假定下次进入编辑模式时会将处理程序添加回来。
答案 2 :(得分:2)
您可以在类中定义私有的eventhandler委托变量,并在构造函数中指定它:
private SaveButtonClickedHandler _handler;
在构造函数中分配处理程序:
_handler = (s,e) => SaveData();
this.globalEvents.OnSaveButtonClicked += _handler;
处置:
this.globalEvents.OnSaveButtonClicked -= _handler;
“SaveButtonClickedHandler”是伪代码/占位符,用于委托名称应该是什么。
Hasanain
答案 3 :(得分:0)
你必须输入一个适当的事件处理程序方法来调用SaveData()
并注册/取消注册。否则,您尝试取消注册另一个“新”匿名方法,而不是您已注册的原始方法,因为它是匿名的,因此无法再实际访问。
public void SaveButtonClicked(object sender, EventArgs e)
{
SaveData();
}
this.globalEvents.OnSaveButtonClicked += SaveButtonClicked;
this.globalEvents.OnSaveButtonClicked -= SaveButtonClicked;