C #: попробуйте / поймать, как очистить текстовое поле, вызвавшее ошибку? - PullRequest
1 голос
/ 10 ноября 2010

Мне интересно, есть ли способ заставить оператор catch очистить текстовое поле, вызвавшее ошибку.Вот мой проверочный код:

private bool ValidateForm()
{
    int val1, direction = 0;
    double speed = 0.0;

    bool validated = false;

    if (txtName.Text != "")
    {
        try
        {
            // attempts to convert values into their primary data types.
            // Any errors will throw an exception that will be reported
            // as invalid data

            val1 = Convert.ToInt32(txtXPos.Text);
            val1 = Convert.ToInt32(txtYPos.Text);
            speed = Convert.ToDouble(txtSpeed.Text);
            direction = Convert.ToInt32(txtDirection.Text);

            validated = true;
        }
        catch
        {
            MessageBox.Show(
              "You have an invalid value entered. Please check your entry.",
              "Invalid Values", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        if (speed < 0.0 || speed > (double)newAirplane.PlanePosition.MaxSpeed)
        {
            MessageBox.Show(
              "Speed entered is out of range.",
              "Invalid Values", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        if (direction < 0 || direction > 359) 
        {
            MessageBox.Show(
              "Direction is out of range",
              "Invalid values", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
    else
    {
        MessageBox.Show(
            "Please enter a name.",
            "Blank Name", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }

    return validated;
}

Ответы [ 7 ]

2 голосов
/ 10 ноября 2010

Предполагая, что это Winforms, лучше всего использовать встроенный ErrorProvider , а не пытаться развернуть собственную платформу проверки.

2 голосов
/ 10 ноября 2010

Вы можете объявить переменную вне блока try:

TextBox lastTextBox = null;

Затем перед каждым преобразованием задайте для этого текстового поля, из которого вы будете получать значение, например:

lastTextBox = txtXPos;
val1 = Convert.ToInt32(txtXPos.Text);

Тогда в вашем блоке catch:

if (lastTextBox != null)
    lastTextBox.Text = "";
1 голос
/ 10 ноября 2010

Вы также можете извлечь логику для одного текстового поля в нечто вроде:

private bool Validated<T>(Control tb, out T value)
{
    try
    {
        value = return (T)Convert.ChangeType(tb.Text, typeof(T));
        return true;
    }
    catch
    {
        value = default(T);
        tb.Text = "";
        return false;
    }
 }

, которое вы можете просто использовать как:

if (!Validated<int>(txtXPos, out val1) ||
    !Validated<int>(txtYPos, out val2) ||
    !Validated<double>(txtSpeed, out speed) ||
    !Validated<int>(txtDirection, out direction))
{
     MessageBox.Show("Validation failed");
}

[Редактировать]

Кроме того, очистка текстовых полей - плохая идея с точки зрения удобства использования, особенно внутри события TextChanged.Я не хотел бы, чтобы мое текстовое поле очищалось, если я случайно наберу письмо внутри.Намного лучше было бы использовать ErrorProvider или незаметно указать, что ввод неправильный каким-либо другим способом.

[Edit2]

Преобразование из строки в примитивные типывозможно с помощью Convert.ChangeType, но вы можете предоставить любой метод преобразования, который вам нравится, если вам нужно проанализировать более сложную строку в свой собственный класс:

private bool Validated<T>(Control tb, Func<string, T> converter, out T value)
{
    try
    {
        value = converter(tb.Text);
        return true;
    }
    catch
    {
        value = default(T);
        tb.Text = "";
        return false;
    }
 }

И затем использовать его следующим образом:

if (!Validated<int>(txtXPos, Convert.ToInt32, out val1) ||
    !Validated<int>(txtYPos, Convert.ToInt32, out val2) ||
    !Validated<double>(txtSpeed, Convert.ToDouble, out speed) ||
    !Validated<int>(txtDirection, Convert.ToInt32, out direction))
{
        MessageBox.Show("Validation failed");
}

Таким образом, вы можете передать любой делегат с подписью Func<string, T>, который будет выполнять фактическое преобразование, или вызвать исключение в случае сбоя.

1 голос
/ 10 ноября 2010

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

Вы должны использовать TryParse методы:

bool xValValid = Int32.TryParse(txtXPos.Text, out val1);
if(!xValValid){
  txtXPos.Text = "";
  validated = false;
  MessageBox.Show("You have an invalid value entered. Please check your entry.", "Invalid Values", MessageBoxButtons.OK, MessageBoxIcon.Error);

}
1 голос
/ 10 ноября 2010

Вместо блоков "Try Catch" я рекомендую вам использовать Int32.TryParse Method и Double.TryParse

0 голосов
/ 10 ноября 2010
    private bool ValidateForm()
            {
                int val1, direction = 0;
                double speed = 0.0;

                bool validated;
                if (txtName.Text != "")
                {
                    try
                    {
                        //attempts to convert values into their primary data types. Any errors will throw an exception that will be reported as invalid data
                        int counter = 1;
                        val1 = Convert.ToInt32(txtXPos.Text);
                        counter = counter + 1;
                        val1 = Convert.ToInt32(txtYPos.Text);
                        counter = counter + 1;
                        speed = Convert.ToDouble(txtSpeed.Text);
                        counter = counter + 1;
                        direction = Convert.ToInt32(txtDirection.Text);
                        validated = true;
                    }
                    catch
                    {
                    switch(counter)

                      case 1:

                     txtXPos.Text="";
                      break;
                      case 2:

                      txtYPos.Text="";
                        break;
                      case 3:

                     txtSpeed.Text="";
                     break;
                     case 4:

                     txtDirection.Text="";
                      break;
                     default:
                     break;
                        MessageBox.Show("You have an invalid value entered. Please check your entry.", "Invalid Values", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        validated = false;
                    }
                    if (speed < 0.0 || speed > (double)newAirplane.PlanePosition.MaxSpeed)
                    {
                        MessageBox.Show("Speed entered is out of range.", "Invalid Values", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        validated = false;
                    }
                    if (direction < 0 || direction > 359)
                        MessageBox.Show("Direction is out of range", "Invalid values", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    MessageBox.Show("Please enter a name.", "Blank Name", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    validated = false;
                }



                return validated;

            }

Думаю, это то, что вы ожидаете.

0 голосов
/ 10 ноября 2010

Я бы предложил создать такую ​​функцию, как

private bool TryReadClear(TextBox txtBox, out double value)
{
  if (double.TryParse(txtBox.Text, out value))
  {
    txtBox.BackColor = Color.White;
    return true;
  }
  else
  {
    txtBox.BackColor = Color.Red;
    txtBox.Text = string.Empty;
    return false;
  }
}

, а затем заменить ваш блок try / catch на этот упрощенный код:

    validated = validated && TryReadClear(txtXPos, out val1);
    validated = validated && TryReadClear(txtYPos, out val1);
    validated = validated && TryReadClear(txtSpeed, out speed);
    validated = validated && TryReadClear(txtDirection, out direction);
    if (!validated)
    {
      MessageBox.Show("You have an invalid value entered. Please check your entry.", "Invalid Values", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }

Преимущество этого метода в том, что онбудет проверять все текстовые поля при каждом проходе и очищать все недействительные.Использование решения @ cdhowie удалит только первый сбой, но не все.

РЕДАКТИРОВАТЬ: Вы даже можете сделать что-нибудь классное, например, установить красный цвет фона, чтобы визуально выделить плохие текстовые поля (отредактированный код выше, чтобы показать пример).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...