我正在尝试创建一个类(在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,这似乎很乱。
答案 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!");
}
}
}
我仍然要尝试这个,但至少编译器没有抱怨。