Search code examples
c#.netvisual-studiomdicurrencymanager

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


I encountered a weird issue that when I detach an MDIChild from its parent, the CurrencyManager PositionChanged event stops working. I got this behaviour in my main application and was able to reproduce it in a simple test app.

It's a WinForms App on .NET 4.8.

The Test App has Form1 as MDIParent and Form2 as an MDIChild. When starting the app, Form1 gets loaded and immediately initializes Form2 and assigns its MDIParent-Property to Form1. Form1 also has a Button to Detach the currently active MDIChild so it can be moved independable.

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 has a DataTable with a CurrencyManager bound to it. The datatable is assigned to a datagridview for this example. When I click on a row in the datagridview, the cm_PositionChanged() event gets raised and the label on that form shows the current position of the 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);
        }
    }
}

However, when I click on the "Detach MDI Child" button on Form1, Form2 gets detached, but the CurrencyManager doesn't work anymore. Apparently the event doesn't even get raised anymore.

I have no clue why this happens.. A wild guess is that this happens because the Form.Handle changes, but its just a gut feeling and I don't know how I would prevent this. Any ideas?

Demo of the issue


Solution

  • I found a solution/workaround that works for me:

    Subscribing to the Form2.HandleCreated-Event, assigning a new BindingContext to the CurrencyManager and then resubscribing to the PositionChanged-Event. Also storing the current position for the users convenience:

        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);
            }
        }