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?

Listener类更改表单上的文本标签

以下是"良好实践"方法之一。

首先,修改你的类如下

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;
    }
}