c# winform delegates for n subforms

2019-09-21 15:08发布

问题:

I have a C# main form that opens up C# sub forms in separate tabs. Each tab is simply an instance of the same sub form so the tab code is like:

SubForm sf = new SubForm();
TabPage tp = new TabPage();
tp.Controls.Add(sf);
tabControl.TabPages.Add(tp);

There can be n tabs and subforms. Then each new subform instance has a delegate to handle external event updates, like so:

public partial class SubForm : Form
{
  ... form setup ...      

  internal void DoStuff(value v)
  {
    if (InvokeRequired)
    {
        // Generic Action delegate
        Invoke(new Action<string, string>(DoStuff), value);
        return;
    }

    myLabel.Text = value;
    Show();
  }
}

Click the subscribe button and there's a Geode registration to specific keys in the subform, and the delegate is passed as an event handler:

private void button_Click(object sender, EventArgs e)
{
  new Geode().RegisterMyListener(cache, key, DoStuff);
}

When the Geode key value is updated then the update is handled.

This is working fine for the 1st subform. Then with a 2nd or 3rd subform all the Geode subscriptions to each subform's keys are updating, but all the updates are being handled only by the most recently instantiated subform's delegate. I had not expected that to happen because doesn't each new subform instance have its own stack with a new delegate?

UPDATE: Once a 2nd key is registered with Geode RegisterMyListener like this:

region.GetSubscriptionService().RegisterKeys(s);
region.AttributesMutator.SetCacheListener(new Listener<string, string>(DoStuff)); 

then every event update references the latest DoStuff delegate and never a previous one. So is a Geode listener a static register? I am looking to be able to subscribe to separate keys with many instances of the same Listener. Is that possible? Or am I going to need multiple listeners for multiple subforms?

回答1:

You can do it with extension method like this:

public static class Extensions
{
    public static void InvokeAction(this Control control, Action action)
    {
        if (control.InvokeRequired)
        {
            control.Invoke(new MethodInvoker(() => { action(); }));
        }
        else
        {
            action();
        }
    }
}

Usage:

public partial class SubForm : Form
{
    public void SetExampleText(string text)
    {
        this.InvokeAction(() => { this.ExampleTextBox.Text = text; })
    }
}