События задержки текстового поля - PullRequest
0 голосов
/ 12 мая 2018

У меня есть форма выбора, в которой пользователь должен вводить параметры для мини-игры, начиная с 8 до 32. Моя проблема в том, что, как только я начинаю печатать, я вставляю число меньше 8 (я хочу поставить20, например), событие активируется, как только я набираю 2 и превращаю его в 8.

private void TXBheight_TextChanged(object sender, EventArgs e)
    {

        if(int.Parse(TXBheight.Text) < 8)
        {
            TXBheight.Text = "8";
        }
        else if (int.Parse(TXBheight.Text) > 32)
        {
            TXBheight.Text = "32";
        }
    }

Есть ли простой способ сделать задержку или подождать, пока я не закончу печатать?

Для тех, кто определяет этот вопрос как возможный дубликат, я посмотрел, и ответы возможные получены 6 лет назад.За это время языки и компиляторы развиваются, поэтому, может быть, есть что-то новое, чему мы все можем научиться у

Ответы [ 5 ]

0 голосов
/ 12 мая 2018

Используйте Microsoft Reactive Framework, и это становится легко.Просто сделайте это:

private void Form1_Load(object sender, EventArgs e)
{
    IObservable<long> query =
        Observable
            .FromEventPattern<EventHandler, EventArgs>(
                h => TXBheight.TextChanged += h,
                h => TXBheight.TextChanged -= h)
            .Select(x => Observable.Timer(TimeSpan.FromMilliseconds(250.0)))
            .Switch()
            .ObserveOn(this);

    IDisposable subscription = query.Subscribe(ep =>
    {
        if (int.Parse(TXBheight.Text) < 8)
        {
            TXBheight.Text = "8";
        }
        else if (int.Parse(TXBheight.Text) > 32)
        {
            TXBheight.Text = "32";
        }
    });
}

Теперь есть задержка 250,0 миллисекунды после того, как последний символ введен до того, как ваш код будет запущен.Если новый символ вводится до истечения 250,0 миллисекунд, запускается новый таймер, а старый не срабатывает.

Код .ObserveOn(this) возвращает таймер обратно в поток пользовательского интерфейса.

Просто NuGet "System.Reactive" и "System.Reactive.Windows.Forms".Также добавьте using System.Reactive.Linq; вверху вашего класса.

0 голосов
/ 12 мая 2018

Вместо использования события TextChanged используйте событие TextBox _Validating и событие _Validated. Событие _Validating вызывается только тогда, когда текстовое поле теряет фокус, т.е. когда пользователь нажимает на другой элемент управления, например, Button или другой TextBox. Когда это происходит, происходит событие _Validating, и вы проверяете значение в текстовом поле. Если он недействителен, вы отменяете событие _Validating. Если он действителен, вы НЕ отменяете _Validating event, и в результате происходит событие _Validated. В _Validated event вы делаете то, что вам нужно делать, когда входные данные верны. Используйте errorprovider, чтобы сообщить пользователю, что введенные данные неверны.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        errorProvider1.SetError(TXBheight, "");

        //NEW NEW NEW
        buttonCancel.CausesValidation = false;
    }

    private void Button1_Click(object sender, EventArgs e)
    {
        // do what is needed when the button is clicked
    }

    private void TXBheight_Validating(object sender, CancelEventArgs e)
    {

        errorProvider1.SetError(TXBheight, "");

        if (String.IsNullOrEmpty(TXBheight.Text))
        {
            errorProvider1.SetError(TXBheight, "Height is a required field");
            e.Cancel = true;
            return;
        }

        if (int.Parse(TXBheight.Text) < 8)
        {
            errorProvider1.SetError(TXBheight, "Height must be GE 8");
            e.Cancel = true;
            return;
        }

        if (int.Parse(TXBheight.Text) > 32)
        {
            errorProvider1.SetError(TXBheight, "Height must be LE 32");
            e.Cancel = true;
            return;
        }

    }

    private void TXBheight_Validated(object sender, EventArgs e)
    {
        //this event is fired when the data is valid, i.e., 
        // if e.Cancel in the _Validating method is NOT set to cancel

    }

    //NEW NEW NEW
    private void ButtonCancel_Click(object sender, EventArgs e)
    {
        AutoValidate = AutoValidate.Disable;
        Close();
    }

    // NEW #2

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (e.CloseReason == CloseReason.UserClosing)
        {
            DialogResult result = MessageBox.Show("Do you really want to exit?", "Dialog Title", MessageBoxButtons.YesNo);
            if (result == DialogResult.Yes)
            {
                Environment.Exit(0);
            }
            else
            {
                e.Cancel = true;
            }
        }
        else
        {
            e.Cancel = true;
        }
    }
}
0 голосов
/ 12 мая 2018

Вы можете использовать return в качестве точки останова, когда пользователь нажимает клавишу ввода, вы запускаете свой код.

Вы можете использовать это с KeypressEvent.

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    char ch = e.KeyChar; // Getting the Key that was pressed

    if (ch == 13) // Checking if it equal to 13 ASCII code for return 
    {
        if (int.Parse(textBox1.Text) < 8)
        {
            textBox1.Text = ""; // emptying the textbox
            textBox1.AppendText("8"); // using AppendText() to keep the cursor at the end
        }
        else if (int.Parse(textBox1.Text) > 32)
        {
            textBox1.Text = "";
            textBox1.AppendText("32");
        }
        e.Handled = true; // To say that the event was handled.
    }
}
0 голосов
/ 12 мая 2018

Простой ответ: (стиль C # 7)

public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
    this.textBox1.TextChanged += TextBox1_TextChanged;
    this.textBox1.Leave += TextBox1_Leave;
  }

  private void TextBox1_TextChanged(object sender, EventArgs e)
  {
    string text = this.textBox1.Text;
    if (!int.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out int number))
    {
      this.textBox1.Text = "";
      return;
    }

    if (number > 32)
    {
      this.textBox1.Text = "32";
    }
  }

  private void TextBox1_Leave(object sender, EventArgs e)
  {
    string text = this.textBox1.Text;
    if (!int.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out int number))
    {
      this.textBox1.Text = "8";
      return;
    }

    if (number > 32)
    {
      this.textBox1.Text = "32";
    }

    if (number < 8)
    {
      this.textBox1.Text = "8";
    }
  }

Обычно я делаю это с помощью управления нажатыми клавишами и изменениями текста (включая вставку) проверить правильность содержимого окна.К сожалению, у меня есть код только для Borland C ++ Builder и VS6 на работе.Воссоздание этого кода не так просто (слишком много кода) , поэтому только простой ответ.

0 голосов
/ 12 мая 2018

Почему бы не создать задачу и проверить, выполнена ли она перед выполнением?

private Task task; //declare it at the top

private void TXBheight_TextChanged(object sender, EventArgs e)
{
   if(task?.Status == TaskStatus.Running) return;

   task =  Task.Run( () =>
   {
        if(int.Parse(TXBheight.Text) < 8)
        {
            TXBheight.Text = "8";
        }
        else if (int.Parse(TXBheight.Text) > 32)
        {
            TXBheight.Text = "32";
        } 
   });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...