C#回调到windows窗体

时间:2015-08-05 18:35:26

标签: c# callback delegates

我正在尝试创建一个类(在Windows应用程序的上下文中),可以通过委托更新进度(或发送一些用户消息)回到主窗体UI。我遇到的问题是,由于缺少对象引用,编译器将不允许我尝试的任何构造。这已经讨论过here,但没有答案与写在表单上的对象有关。

在c ++中我会这样做:

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

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

//这样任何地方的任何函数都可以更新列表框(线程安全除外)

在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!");
        }
    }
}

我理解必须为委托分配静态方法的问题,而Form1方法是非静态的。我想使用委托方法,因为它似乎是最干净的;我只是找不到一种方法来写这个以使其工作,而不是将指针传回Form,这似乎很乱。

1 个答案:

答案 0 :(得分:0)

我相信我刚刚遇到了答案。您必须公开对UI对象的静态引用,在本例中为ListBox。然后,您可以将回调委托分配给一个函数,以确保列表框引用不为null。您只需要确保在创建表单时分配静态引用:

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

我仍然要尝试这个,但至少编译器没有抱怨。