【问题标题】:C# callbacks into windows formsC# 回调到 Windows 窗体
【发布时间】:2015-10-28 16:27:48
【问题描述】:

我正在尝试创建一个类(在 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 方法是非静态的。我想使用委托方法,因为它看起来最干净;我只是找不到一种方法来编写它以使其工作,除了将指针传递回表单,这看起来很乱。

【问题讨论】:

    标签: c# callback delegates


    【解决方案1】:

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

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

    我还是要试试这个,但至少编译器没有抱怨。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-23
      • 1970-01-01
      • 2011-05-31
      • 1970-01-01
      相关资源
      最近更新 更多