CurrencyManager PositionChanged-Event 在 Form 与其 MDIParent 分离后停止工作

CurrencyManager PositionChanged-Event stops working after Form gets detached from its MDIParent

我遇到了一个奇怪的问题,当我将 MDIChild 从其父级分离时,CurrencyManager PositionChanged 事件停止工作。我在我的主应用程序中遇到了这种行为,并且能够在一个简单的测试应用程序中重现它。

这是 .NET 4.8 上的 WinForms 应用程序。

测试应用将 Form1 作为 MDIParent,将 Form2 作为 MDIChild。启动应用程序时,Form1 被加载并立即初始化 Form2 并将其 MDIParent-属性 分配给 Form1。 Form1 也有一个按钮来分离当前活动的 MDIChild,因此它可以独立移动。

public partial class Form1 : Form
{
    private void Form1_Load(object sender, EventArgs e)
    {
        Form2 frm = new Form2();
        frm.MdiParent = this;
        frm.Show();
    }

    private void btnDetachMDIChild_Click(object sender, EventArgs e)
    {
        if (ActiveMdiChild != null)
        {
            ActiveMdiChild.MdiParent = null;
        }
    }
}

Form2 有一个绑定了 CurrencyManager 的 DataTable。对于这个例子,数据表被分配给一个数据网格视图。当我单击数据网格视图中的一行时,将引发 cm_PositionChanged() 事件并且该表单上的标签显示 CurrencyManager 的当前位置:

public partial class Form2 : Form
{

    DataTable dt;
    CurrencyManager cm;

    private void Form2_Load(object sender, EventArgs e)
    {
        prepareTable();
        fillTable();

        cm.PositionChanged += new EventHandler(cm_PositionChanged);
    }

    private void cm_PositionChanged(object sender, EventArgs e)
    {
        lblPos.Text = cm.Position.ToString();
    }

    private void prepareTable()
    {
        dt = new DataTable();
        dt.Columns.Add("Index", typeof(int));
        cm = (CurrencyManager)this.BindingContext[dt];

        dgv.DataSource = dt;
    }

    private void fillTable()
    {
        for (int i = 0; i < 100; i++)
        {
            dt.Rows.Add(i);
        }
    }
}

但是,当我单击 Form1 上的“分离 MDI 子项”按钮时,Form2 分离,但 CurrencyManager 不再工作。显然,该事件甚至不再引发。

我不知道为什么会发生这种情况。一个疯狂的猜测是,这种情况发生是因为 Form.Handle 发生了变化,但这只是一种直觉,我不知道如何防止这种情况发生。有什么想法吗?

我找到了适合我的solution/workaround:

订阅 Form2.HandleCreated-Event,将新的 BindingContext 分配给 CurrencyManager,然后重新订阅 PositionChanged-Event。还存储当前位置以方便用户:

    private void Form2_Load(object sender, EventArgs e)
    {
        prepareTable();
        fillTable();

        cm.PositionChanged += new EventHandler(cm_PositionChanged);
        this.HandleCreated += new EventHandler(Form2_HandleCreated);
    }

    private void Form2_HandleCreated(object sender, EventArgs e)
    {
        if (dt != null)
        {
            int pos = -1;
            if (cm != null) { pos = cm.Position; }
            cm = (CurrencyManager)this.BindingContext[dt];
            cm.Position = pos;
            cm.PositionChanged -= cm_PositionChanged;
            cm.PositionChanged += new EventHandler(cm_PositionChanged);
        }
    }