【问题标题】:How to make a program wait for user to type in a textbox?如何让程序等待用户输入文本框?
【发布时间】:2022-08-13 21:46:18
【问题描述】:

当我将 WinForm 程序运行到一行时,我想检查一个文本框是否已经有用户输入,如果没有,我会要求用户输入文本框并等到用户输入一些输入,然后再运行下一行编码。我想知道如何等待?

程序必须等待所需的信息作为下一行代码的输入。

谢谢。

  • 不需要花哨的计时器并检查文本框内容是否更改。我只需订阅文本框的TextChanged 事件并在触发该事件时做出反应。
  • 这不是 GUI 的工作方式。如果您等待,UI 将挂起并且用户无法输入任何内容。但是,您可以对 TextChanged 事件做出反应,然后从那里进行下一个处理步骤
  • 不要等待,使用eventControl.TextChanged Event 一样,在满足条件时执行一些代码。
  • @Cleptus程序必须等待下一行代码输入所需的信息。
  • @Tim:这就是为什么几乎所有的 GUI 都是这样操作的:首先填写所有输入框,然后按一个按钮。按下按钮时工作完成。在填充文本框之前没有需要等待的“下一行代码”,因为代码甚至在用户填写所有内容并按下按钮之前都不会运行。

标签: c# winforms


【解决方案1】:

等待 GUI 中发生的事情(使用计时器、来自其他线程的循环等)是对资源的巨大浪费。
几乎所有函数式编程语言都有Events,包括C#

来自维基百科:

事件驱动编程是一种编程范式,其中流 程序由事件决定,例如用户操作(鼠标 点击、按键)、传感器输出或从其他 程序或线程。事件驱动编程是主导范式 用于图形用户界面和其他应用程序(例如, JavaScript Web 应用程序)以执行某些操作为中心 响应用户输入的动作。编程也是如此 用于设备驱动程序(例如,USB 设备驱动程序堆栈中的 P)。

Textbox 控件继承的Control.TextChanged 事件的帮助下,您可以这样做:

private void Form1_Load(object sender, EventArgs e)
{
    ValidateGUI();
}

private const int MIN_CHARS_TO_DO_SOMETHING = 8;
private const string NOT_VALID = "Oh No There is No User Input )-:";
private const string VALID = "Great We Can Do Something (-:";

private void textBox1_TextChanged(object sender, EventArgs e)
{
    ValidateGUI();
}

private void ValidateGUI()
{
    if (textBox1.Text.Length < MIN_CHARS_TO_DO_SOMETHING)
    {
        lblMessege.Text = NOT_VALID;
    }
    else
    {
        lblMessege.Text = VALID;
        // Execute some code..
        //...
        //...                  
    }
}

【讨论】:

    【解决方案2】:

    我将假设您有正当理由等待而不是监视输入。

    您只需要使用后台工作人员,然后您需要将 DoWork 事件设置为等待指定的时间,并设置 RunWorkerCompleted 事件来运行您的代码检查是否正在输入。

    这是一个假设标签和文本框已经在表单上的示例。或者,您可以将后台工作人员添加为表单元素,而不是在代码中创建它:

        public Form1()
        {
            InitializeComponent();
            waitForInput();
        }
        
        private void waitForInput()
        {
            BackgroundWorker waiter = new BackgroundWorker();
            waiter.WorkerSupportsCancellation = true;
            waiter.WorkerReportsProgress = true;
            waiter.DoWork += wait10Seconds;
            waiter.RunWorkerCompleted += doneWaiting;
            waiter.RunWorkerAsync();
            
        }
    
        private void wait10Seconds(object sender, DoWorkEventArgs e)
        {
            System.Threading.Thread.Sleep(10000);
        }
        private void doneWaiting(object sender, RunWorkerCompletedEventArgs e)
        {
            if(textBox1.Text == "")
            {
                label1.Text = "Why haven't you typed anything?";
            }
        }
    

    【讨论】:

    • 后台工作者?为了这?如果需要(并且根据 OP,它不是),您可以使用 System.Windows.Forms.Timer 并将其 Interval 设置为 10000
    【解决方案3】:

    如果我理解你的意思,像SemaphoreSlim 这样的同步对象可能非常适合这样的事情。此声明将初始计数设置为 0,因此信号量将阻塞。 initSync 方法中途暂停,并在执行下一行之前将await TextChanged 事件释放semaphoreSlim。但是,UI 线程是不是在等待期间被阻止。

    SemaphoreSlim _waitForText = new SemaphoreSlim(0, 1);
    private async Task initAsync()
    {
        richTextBox1.AppendText(
                $"The async method that populates this RichTextBox waits for input.");
        richTextBox1.AppendText($"{Environment.NewLine}>");
    
        await _waitForText.WaitAsync();
    
        richTextBox1.AppendText(
            $"{Environment.NewLine}Now this method will complete, and you'll see a message box in 5 seconds");
    }
    


    例子

    public MainForm()
    {
        InitializeComponent();
    
        // Subscribe to TextChanged event
        textBox1.TextChanged += (sender, e) => 
        {
            if(textBox1.Text.Any())
            {
                try
                {
                    // Is count is already 1, decrement it.
                    if (_waitForText.Wait(0))
                    {
                        // This ensures the maxCount won't be exceeded
                    }
                    else
                    {
                        // The semaphore could NOT be entered. 
                        richTextBox1.AppendText($"{textBox1.Text}");
                    }
                }
                finally
                {
                    _waitForText.Release();
                }
            }
        };
    }
    protected override async void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        await initAsync();
        await Task.Delay(TimeSpan.FromSeconds(5));
        MessageBox.Show("All done");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多