Listener类更改表单上的文本标签
本文关键字:文本标签 表单 Listener | 更新日期: 2023-09-27 18:19:32
我在C#中有以下类:
public class LeapEventListener : Listener
{
public override void OnFrame(Controller controller)
{
Console.WriteLine("New Frame");
// process frame data...
}
public override void OnInit(Controller controller)
{
Console.WriteLine("Initialized");
}
public override void OnConnect(Controller controller)
{
Console.WriteLine("Connected");
//If using gestures, enable them:
controller.EnableGesture(Gesture.GestureType.TYPE_CIRCLE);
}
//Not dispatched when running in debugger
public override void OnDisconnect(Controller controller)
{
Console.WriteLine("Disconnected");
}
}
并在表单加载时调用它:
controller.AddListener(listener);
我知道从类中更改标签不是一个好主意,而且违反了一些编程范式,但我如何更改标签文本而不是Console.WriteLine?
以下是"良好实践"方法之一。
首先,修改你的类如下
public class LeapEventListener : Listener
{
private string status = string.Empty;
public string Status { get { return status; } }
public event EventHandler StatusChanged;
private void SetStatus(string value)
{
if (value == null) value = string.Empty;
status = value;
var handler = StatusChanged;
if (handler != null) handler(this, EventArgs.Empty);
}
public override void OnFrame(Controller controller)
{
SetStatus("New Frame");
// process frame data...
}
public override void OnInit(Controller controller)
{
SetStatus("Initialized");
}
public override void OnConnect(Controller controller)
{
SetStatus("Connected");
//If using gestures, enable them:
controller.EnableGesture(Gesture.GestureType.TYPE_CIRCLE);
}
//Not dispatched when running in debugger
public override void OnDisconnect(Controller controller)
{
SetStatus("Disconnected");
}
}
我所做的只是添加一个公共只读属性、一个设置它的私有方法和一个公共属性更改事件。
然后只需在表单加载中添加以下行(当然是在创建listener
之后):
yourLabel.DataBindings.Add("Text", listener, "Status");
你就完了。
更新:根据您的评论:
(A) 如果要附加到RichTextBox
。数据绑定只适用于属性,因此在这种情况下,您可以简单地附加一个事件处理程序,如下所示:
listener.StatusChanged += (_sender, _e) =>
{
yourRichTextBox.AppendText(listener.Status);
};
(B) 如果侦听器方法是从非UI线程调用的,那么忘记数据绑定,使用上面的事件处理程序,但方式略有不同:
Action onStatusChanged = () =>
{
// Whatever UI element you want to update
yourLabel.Text = listener.Status;
yourRichTextBox.AppendText(listener.Status);
};
listener.StatusChanged += (_sender, _e) =>
{
if (InvokeRequired)
Invoke(onStatusChanged);
else
onStatusChanged();
};
您需要将侦听器实现耦合到一个标签:
public class LeapEventListener : Listener
{
public LeapEventListener(Label lbl)
{
if (lbl == null) {
throw new ArgumentNullException("lbl");
}
this.lbl = lbl;
}
private readonly Label lbl;
public override void OnFrame(Controller controller)
{
lbl.Text = "New Frame";
// process frame data...
}
public override void OnInit(Controller controller)
{
lbl.Text = "Initialized";
}
public override void OnConnect(Controller controller)
{
lbl.Text = "Connected";
//If using gestures, enable them:
controller.EnableGesture(Gesture.GestureType.TYPE_CIRCLE);
}
//Not dispatched when running in debugger
public override void OnDisconnect(Controller controller)
{
lbl.Text = "Disconnected";
}
}
实例化侦听器时,从表单传递标签。
编辑:我认为这是一个干净的设计,因为Listener
基类和您的窗体是弱耦合的。这些类之间的唯一连接集中在这个LeapEventListener
类中,该类充当桥接器。
如果您在这个监听器中做得更多(取决于"流程框架数据"的含义),您可能需要添加一个额外的继承层,它只做工作并调用一个显示状态的抽象方法:
public abstract class LeapEventListener : Listener
{
protected abstract void DisplayStatus(string message);
public override void OnFrame(Controller controller)
{
DisplayStatus("New Frame");
// process frame data...
}
public override void OnInit(Controller controller)
{
DisplayStatus("Initialized");
}
public override void OnConnect(Controller controller)
{
DisplayStatus("Connected");
//If using gestures, enable them:
controller.EnableGesture(Gesture.GestureType.TYPE_CIRCLE);
}
//Not dispatched when running in debugger
public override void OnDisconnect(Controller controller)
{
DisplayStatus("Disconnected");
}
}
public class LabelLeapEventListener : LeapEventListener
{
public LabelLeapEventListener(Label lbl)
{
if (lbl == null) {
throw new ArgumentNullException("lbl");
}
this.lbl = lbl;
}
private readonly Label lbl;
protected override void DisplayStatus(string message)
{
lbl.Text = message;
}
}