如何避免WPF中事件的递归触发?

我有两个WPF(来自标准集)小部件A和B.当我更改A的某个属性时,它应该设置在B上,当它在B中更改时,它应该设置为A.

现在我有这个丑陋的递归 - >我改变了A,所以代码改变了B,但是因为B改变了,它改变了A,所以它改变了B ...你有图片。

如何避免这种递归最“标准”的方式? 天真的删除和添加事件处理程序不起作用,并且检查新值是否与旧值相同在此不适用(由于计算的波动 - 我没有将相同的值设置为A和B,而是进行了转换) 。

背景

为了避免混淆,我总是尽量提供有关问题的最少信息。 但是,这可能会有所帮助

  • 我没有写这些小部件,我只是处理事件,就这些
  • 尽管标题为“递归触发”,处理程序依次调用,因此您具有序列入口 - 出口 - 入口 - 出口 - 出口 - 出口,而不是入口 - 入口 - 出口 - 出口 - 出口 - 出口

    最后,可能是最不重要的,但是

  • 在这种特殊情况下,我有A和B的共同处理程序
  • A和B(在这种情况下)是scrollviewers,我试图按比例保持他们两人的相同位置。 该项目(由卡琳胡贝尔)在这里:http://www.codeproject.com/KB/WPF/ScrollSynchronization.aspx

    事件触发

    阻塞事件的想法非常流行,我添加了触发事件的顺序,下面我们来看看:

  • 我改变了A
  • 一个处理程序被调用
  • 我禁用A的处理程序
  • 我改变B(这是存储的,但没有触发)
  • 我启用A的处理程序
  • 现在事件从队列中获得
  • B处理程序被调用
  • 我禁用B的处理程序
  • 我改变A.
  • ...
  • 如你所见,这是徒劳的。


    重新构建代码,以便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

    上一篇: How to avoid recursive triggering of events in WPF?

    下一篇: ASP.NET MVC or WebForms?