我有两个 WPF(来自标准集)小部件 A 和 B。当我更改 A 的某些属性时,它应该设置在 B 上,当它在 B 中发生更改时,它应该设置在 A 上。
现在我有这个丑陋的递归 --> 我改变了 A,所以代码改变了 B,但是由于 B 改变了,它改变了 A,所以它改变了 B...你有图片。
如何以最“标准”的方式避免这种递归?天真的删除和添加事件处理程序不起作用,检查新值是否与旧值相同在这里不适用(因为计算的波动——我不是为 A 和 B 设置相同的值,而是转换) .
背景
我总是尽量减少有关问题的信息以避免混淆。但是,这可能会有所帮助
- 我没有编写那些小部件,我只是处理事件,仅此而已
尽管标题为“递归触发”,但处理程序是按顺序调用的,因此您的顺序是入口-导出-入口-导出-入口-导出,而不是入口-入口-入口-导出-导出-导出
最后一个,可能是最不重要的,但无论如何
- 在这种特殊情况下,我有 A 和 B 的通用处理程序
A 和 B(在本例中)是滚动查看器,我尝试按比例为它们保持相同的位置。该项目(由 Karin Huber 设计)在这里: http://www.codeproject.com/KB/WPF/ScrollSynchronization.aspx
事件触发
阻塞事件的想法非常流行,我添加了触发事件的顺序,我们开始吧:
- 我改变了A
- 处理程序被调用
- 我禁用 A 的处理程序
- 我更改 B(这是存储的,但未触发)
- 我启用 A 的处理程序
- 现在事件从队列中获取
- B处理程序被调用
- 我禁用 B 的处理程序
- 我改A
- ...
如你所见,这是徒劳的。
最佳答案
首先,我会考虑设计,因为那些循环依赖通常是糟糕设计的标志。
但是,在某些情况下,这种依赖关系可能是唯一的出路。在这些情况下,我建议使用私有(private)标志来指示 B 中的变化是否是由 A 中的变化引起的。像这样(已更新):
public class A
{
private bool m_ignoreChangesInB = false;
private void B_ChangeOccurred(object sender, EventArgs e)
{
if (!m_ignoreChangesInB)
{
// handle the changes...
}
}
private void SomeMethodThatChangesB()
{
m_ignoreChangesInB = true;
// perform changes in B...
m_ignoreChangesInB = false;
}
}
B类中应该使用相同的方法。但是,这种方法不处理来自多个线程的更改。如果 A 或 B 可能同时从多个线程更改,您将必须使用适当的技术来避免属性更改丢失。
关于c# - 如何避免在 WPF 中递归触发事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3574715/