如何避免WPF中事件的递归触发?
我有两个WPF(来自标准集)小部件A和B.当我更改A的某个属性时,它应该设置在B上,当它在B中更改时,它应该设置为A.
现在我有这个丑陋的递归 - >我改变了A,所以代码改变了B,但是因为B改变了,它改变了A,所以它改变了B ...你有图片。
如何避免这种递归最“标准”的方式? 天真的删除和添加事件处理程序不起作用,并且检查新值是否与旧值相同在此不适用(由于计算的波动 - 我没有将相同的值设置为A和B,而是进行了转换) 。
背景
为了避免混淆,我总是尽量提供有关问题的最少信息。 但是,这可能会有所帮助
尽管标题为“递归触发”,处理程序依次调用,因此您具有序列入口 - 出口 - 入口 - 出口 - 出口 - 出口,而不是入口 - 入口 - 出口 - 出口 - 出口 - 出口
最后,可能是最不重要的,但是
A和B(在这种情况下)是scrollviewers,我试图按比例保持他们两人的相同位置。 该项目(由卡琳胡贝尔)在这里:http://www.codeproject.com/KB/WPF/ScrollSynchronization.aspx
事件触发
阻塞事件的想法非常流行,我添加了触发事件的顺序,下面我们来看看:
如你所见,这是徒劳的。
重新构建代码,以便A和B的事件处理程序调用另一种方法来完成实际工作,而不是提高事件。
private void EventHandlerA(object sender, EventArgs e)
{
ChangeA();
ChangeB();
}
private void EventHandlerB(object sender, EventArgs e)
{
ChangeB();
ChangeA();
}
如果您需要直接或通过B更改A,则可以扩展/更改这些方法。
UPDATE
鉴于您无法更改/无法访问代码,因此这不是解决方案。
首先,我会考虑设计,因为这些循环依赖通常是设计不好的标志。
但是,可能会出现这种依赖关系是唯一出路的情况。 在这种情况下,我会建议使用私有标志来指示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可能同时从多个线程中更改,则必须使用适当的技术来避免属性更改丢失。
ChrisFs解决方案可能是最佳选择,但有时我们会删除事件,进行更改并重新添加事件处理程序:
想象一下DataContext和DataContextChanged事件:
DataContextChanged -= OnDataContextChanged;
DataContext = new object();
DataContextChanged += OnDataContextChanged;
这样,你肯定会知道你的事件处理程序不会停下来说话。 但事件仍然发生;)。
链接地址: http://www.djcxy.com/p/47517.html