从 C# 中的类更新 GUI 的正确方法
Posted
技术标签:
【中文标题】从 C# 中的类更新 GUI 的正确方法【英文标题】:Correct way to update a GUI from a class in C# 【发布时间】:2018-11-18 11:11:30 【问题描述】:我正在寻找一种方法来从我想要独立而不依赖于 GUI 的类中更新 GUI。它是一个由监听器和客户端组成的网络类。这个类可以连接然后发送/接收数据。我希望这些数据能够使用 GUI 显示,但在类本身中没有任何与 GUI 相关的代码。
所以简而言之,网络类只知道自己。 GUI 知道网络类。
这是我要添加代码的地方
public void ReceiveBytes()
byte[] receivedPacket;
while (IsListeningForBytes)
receivedPacket = new byte[Packet.BUFFERSIZE];
try
int bytesRead = ClientSocket.Receive(receivedPacket, SocketFlags.None);
if (bytesRead > 0)
SocketObject.ProcessMessage(receivedPacket);
// Update GUI here after the message has been processed.
else
throw new Exception("No bytes read");
catch (Exception ex)
IsListeningForBytes = false;
Disconnect();
Console.WriteLine(ex.Message);
编辑:对不起大家,我会尽量让事情更清楚。我正在使用 Windows 窗体,为了这个练习,我们会说我有三个不同的控件:一个列表框、一个组合框和一个文本框,它们将根据发送的内容获取数据。 (我的实际应用程序有需要更新的列表框、组合框、复选框等)。
我知道我不应该从我的对象中引用 GUI,因此我的问题。
至于相关代码,不知道你想看什么。
我已阅读有关事件处理程序和委托的信息,但我不确定在这种情况下如何实际实现它。我最初将 GUI 更新方法作为操作传递给在需要时调用的类,但这似乎很冗长,并没有专门更新我想要的控件。
感谢您迄今为止的帮助。
【问题讨论】:
发布一些相关代码...顺便说一句,您可以使用Task
您使用的是哪个 UI 框架?表格?吗?控制台?
附言;如果您让调用者决定:只需实现要引发的事件。
很难猜出你想把数据放在哪里,但这里有一个例子,你有一个表单 1 中的文本框,你想从类 1 中填充它,然后制作一个方法,它需要一个字符串作为参数,并填充文本框。这个方法应该在 Form1 类中。然后从课堂上调用它。公共填充文本框(字符串数据) textBox1.Text = data; 然后从类 1 调用这个方法,如果你放一些代码,我们将能够提供更多帮助
【参考方案1】:
直接从您的对象更新您的 UI 将违反 OOP。
相反,实现一个事件让调用者/用户知道发生了什么事,并让他们负责更新 UI。
这是一个例子:
//added event, SomeDataObject is for you to create.
public event EventHandler<SomeDataObject> MessageProcessed;
public void ReceiveBytes()
byte[] receivedPacket;
while (IsListeningForBytes)
receivedPacket = new byte[Packet.BUFFERSIZE];
try
int bytesRead = ClientSocket.Receive(receivedPacket, SocketFlags.None);
if (bytesRead > 0)
SocketObject.ProcessMessage(receivedPacket);
// no UI update but fire an event
MessageProcessed?.Invoke(this, new SomeDataObject());
else
throw new Exception("No bytes read");
catch (Exception ex)
IsListeningForBytes = false;
Disconnect();
Console.WriteLine(ex.Message);
见:
Understanding events and event handlers in C#
或
https://msdn.microsoft.com/en-us/library/db0etb8x(v=vs.110).aspx
或
https://duckduckgo.com/?q=EventHandler+C%23&t=h_&ia=qa
更新
那么,它是如何工作的:
在你的 FooGUI 类中,你需要订阅事件。
//so, your UI, can be a window, a form or ... console.
//I'll call your class BytesReceiver
public class FooGUI
BytesReceiver _receiver = new BytesReceiver();
//somewhere, in some function your listener has started
void Init()
//we added an event earlier, now attach a handler.
//a handler is a function, bound to some signature (as defined by the delegate)
//which will be executed when the event is triggered.
//so again; we bind a function to the event, which is invoked when the event is
//raised.
//keep in mind: the Invoke take place on the other thread; so the handler
//runs on that same thread.
//there is no magical polling taking place: it's just a
//function call (from receiver).
//note: there are various ways to bind a function: I'll use lambda here
_receiver.MessageProcessed += (sender,e) =>
//update GUI here.
//since there your while loop waits for a long time
//there must be some non-blocking operation, presumably on another thread.
_receiver.StartListening();
【讨论】:
所以如果我使用你的例子,我如何从引发的事件中更新 GUI?我是否经常从 GUI 中寻找这个事件?这就是我感到困惑的地方。 我会更新答案。您可能想深入研究基本的事件处理。尝试教程;-)以上是关于从 C# 中的类更新 GUI 的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
无法从使用 c# 在不同线程上运行的另一个页面 User.cs 更新 GUI (MainWindow.xaml) 中的进度条