0

I'm trying to create a class (in the context of a Windows Application) that can update progress (or send some user message) back to the main form UI via delegates. The problem I have is that the compiler won't allow any of the constructs I attempt because of missing object references. This has been discussed here but no answers had to do with writing to an object on a Form.

in c++ I would do this:

void LogToUI(string s)
{
    if(Form1)
        Form1->update(s);
}

void TForm1::update(string s)
{
    listbox->Items->Add(s);
}

// so that any function, anywhere, can update the listbox (thread safety aside)

in C#:

namespace test
{
    public delegate void callback(String msg);


    public partial class Form1 : Form
    {
        public void writeToListbox(String s)
        {
            listbox.Items.Add(s);
        }
        public static void writeToConsole(String s)
        {
            System.Console.WriteLine(s);
        }
        public void createclass
        {
            callback ui_update = writeToConsole;  // this is ok
            callback ui_update = writeToListbox;  // not allowed
            someclass SC = new someclass(ui_update);
        }
    }

    class someclass
    {
        callback cb;
        void someclass(callback T)
        {
            this.cb = T;
        }       
        void logthis(string s)
        {
            cb("it's me!");
        }
    }
}

I understand the problem with having to assign a static method to the delegate, and the Form1 method is non-static. I would like to use the delegate method because it seems the cleanest; I just can't find a way to write this in such a way as to make it work, short of passing a pointer back to the Form, which seems messy.

Community
  • 1
  • 1
buzzard51
  • 1,372
  • 2
  • 23
  • 40

1 Answers1

0

I believe I just came across the answer. You have to expose a static reference to a UI object, in this case a ListBox. Then you can assign the callback delegate to a function that makes sure the listbox reference is not null. You just need to make sure you assign the static reference when the form is created:

namespace test
{
    public delegate void callback(String msg);


    public partial class Form1 : Form
    {
        public static ListBox callbackListBox;       //  add this

        public void writeToListbox(String s)
        {
            if(null == callbackListBox)return;       // add this check

            // also make this threadsafe:
            if (callbackListBox.InvokeRequired)
            {
                callbackListBox.Invoke(new MethodInvoker(() => { writeToListbox(s); }));
            }else{
                callbackListBox.Items.Add(s);
                callbackListBox.TopIndex = callbackListBox.Items.Count - (callbackListBox.Height / callbackListBox.ItemHeight);
            }
        }

        public static void writeToConsole(String s)
        {
            System.Console.WriteLine(s);
        }
        public void createclass
        {
            callback ui_update = writeToListbox;     // now OK
            someclass SC = new someclass(ui_update);
        }

        // and add this to the form's constructor:
        public Form1()
        {
            InitializeComponent();
            callbackListBox = listbox1;
        }

    }

    class someclass
    {
        callback cb;
        void someclass(callback T)
        {
            this.cb = T;
        }       
        void logthis(string s)
        {
            cb("it's me!");
        }
    }
}

I still have to try this, but at least the compiler is not complaining.

buzzard51
  • 1,372
  • 2
  • 23
  • 40