c# - 如何避免在 WPF 中递归触发事件?

标签 c# wpf events recursion

我有两个 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/

相关文章:

c# - 基于 DateTime 属性 C#、XPath 对 XML 节点进行排序

c# - 从 ResourceStream 获取图标

c# - 位图图像和位图

wpf - 使用 WebBrowser 控件时 IE 11 WebGL 性能变慢

javascript - jQuery仅隐藏单击的特定表行onclick事件

javascript - 为什么 javascript 在具有共享/部分 View 的 asp.net mvc View 中不起作用

c# - 命名空间 'SQLite' 中不存在类型或命名空间名称 'System.Data'

c# - 使用外键从游标中检索 SQLite 中的数据 - android c# xamarin

javascript - 使用 javascript onmousemove 更改动画 css 属性?

javascript - 如何注册 document.onkeypress 事件