Невозможно привести объект Type1 к типу Type2?


Я пытаюсь проверить кучу элементов управления в GroupBox в приложении, основанном на форме.

Я не могу сопоставить ComboBox приложению, чтобы оно распознало и сгенерировало ошибку, и оно делает это только для TextBox.

private void groupBox1_Validating(object sender, CancelEventArgs e)
{
    foreach (Control control in groupBox1.Controls)
    {
        string controlType = control.GetType().ToString();
        var lst = new List<string>() { "System.Windows.Forms.TextBox" ,"System.Windows.Forms.ComboBox"};

        //if (controlType == "System.Windows.Forms.TextBox")
        if (lst.Contains(controlType, StringComparer.OrdinalIgnoreCase))
        {
            TextBox txtBox = (TextBox)control;
            ComboBox combo = (ComboBox)control;
            if (string.IsNullOrEmpty(txtBox.Text) && string.IsNullOrEmpty(combo.Text))
            {
                MessageBox.Show(txtBox.Name + " Can not be empty");
            }
        }
    }
}

Вот ошибка, которую я получаю:

Невозможно привести объект типа ' System.Окна.Формы.Система ComboBox 'to type'.Окна.Формы.Текстовое поле".

5 2

5 ответов:

Поскольку вы просто хотите проверить свойство Text и Name, а также потому, что оба класса TextBox и ComboBox наследуются от класса Control, вам не нужно здесь выполнять приведение. Это должно работать для вас:

foreach (Control control in groupBox1.Controls)
{
    if (!lst.Contains(control.GetType().ToString(), StringComparer.OrdinalIgnoreCase)) continue;
    if (string.IsNullOrEmpty(control.Text) && string.IsNullOrEmpty(control.Text))
    {
        MessageBox.Show(control.Name + " Can not be empty");
    }
}

Или с помощью Linq:

foreach (Control control in from Control control in groupBox1.Controls 
                                    where lst.Contains(control.GetType().ToString(), StringComparer.OrdinalIgnoreCase)
                                    where string.IsNullOrEmpty(control.Text) && string.IsNullOrEmpty(control.Text) 
                                    select control)
{
    MessageBox.Show(control.Name + " Can not be empty");
}

В коде он приводит любое текстовое поле и любую комбинацию в текстовое поле и комбинацию.

Вам нужно бросить его в то, что он есть только.

private void groupBox1_Validating(object sender, CancelEventArgs e)
{
    foreach (Control control in groupBox1.Controls)
    {
        if (control is ComboBox)
        {
            ComboBox combo = (ComboBox)control;
            if (string.IsNullOrEmpty(combo.Text)) MessageBox.Show(combo.Name + " Can not be empty");
        }
        else if (control is TextBox)
        {
            TextBox txtBox = (TextBox)control;
            if (string.IsNullOrEmpty(txtBox.Text)) MessageBox.Show(txtBox.Name + " Can not be empty");
        }
    }
}

Если у groupbox есть только textbox и combobox, вы также можете сделать:

private void groupBox1_Validating(object sender, CancelEventArgs e)
{
    foreach (dynamic control in groupBox1.Controls)
    {               
        if (string.IsNullOrEmpty(control.Text)) MessageBox.Show(control.Name + " Can not be empty");              
    }
}

Давайте подытожим, что вы хотите сделать:

  1. для каждого элемента управления внутри groupBox1
  2. ... типа TextBox или ComboBox
  3. проверьте, что элемент управления не пуст, если это так, покажите окно сообщения

Вот некоторые важные моменты:

  1. каждый элемент управления, который наследуется от Control, имеет свойство public Text, Вам не обязательно знать, является ли он текстовым полем или комбинацией для этой части
  2. никакой контроль не является и текстовым полем и combobox (то есть ни один класс управления не наследуется от TextBox и ComboBox), поэтому один из этих приведений будет завершаться неудачей каждый раз, когда
  3. вы могли бы использовать as вместо жесткого приведения, которое вернуло бы null в приведении приведения, которое не может быть сделано, но с точкой 1. выше этого нет необходимости

Итак, вот переписанный код с вышеуказанным знанием:

private void groupBox1_Validating(object sender, CancelEventArgs e)
{
    foreach (Control control in groupBox1.Controls)
    {
        if (!(control is TextBox || control is ComboBox))
            continue;
        if (!string.IsNullOrEmpty(control.Text))
            continue;
        MessageBox.Show(control.Name + " Can not be empty");
    }
}

Обратите внимание, что если вы хотите делать и другие вещи, которые должны были бы знать, является ли элемент управления текстовым полем или combobox, я бы вместо этого переписал его следующим образом:

private void groupBox1_Validating(object sender, CancelEventArgs e)
{
    foreach (Control control in groupBox1.Controls)
    {
        var textbox = control as TextBox;
        if (textbox != null)
        {
            ... do your processing of textboxes here
            continue;
        }
        var combobox = control as ComboBox;
        if (combobox != null)
        {
            ... do your processing of comboboxes here
            continue;
        }
        ... do your processing of other controls here
    }
}

Используйте оператор is, чтобы проверить, правильный ли у вас тип:

if(control is TextBox)
{
  TextBox txtBox = (TextBox)control;

  // Do something with txtBox
  if (string.IsNullOrEmpty(txtBox.Text))
  {
      MessageBox.Show(txtBox.Name + " Can not be empty");
  }
}

if(control is ComboBox)
{
  ComboBox combo = (ComboBox)control;

  // Do something with combo
  if (string.IsNullOrEmpty(combo.Text))
  {
      MessageBox.Show(combo.Name + " Can not be empty");
  }
}

As @LasseV.Карлсен отметил, что я выбирал длинный маршрут, индивидуально добавляя в каждый контроль. Я просто добавил контроль вместо чего-то, а не конкретные элементы управления.

Вот как теперь выглядит мой обновленный код:

foreach (Control control in groupBox1.Controls)
        {
            string controlType = control.GetType().ToString();
            var lst = new List<string>() { "System.Windows.Forms.TextBox" ,"System.Windows.Forms.ComboBox"};

            //if (controlType == "System.Windows.Forms.TextBox")
            if (lst.Contains(controlType, StringComparer.OrdinalIgnoreCase))
            {
               // TextBox txtBox = (TextBox)control;
               // ComboBox combo = (ComboBox)control;
                if (string.IsNullOrEmpty(control.Text) && string.IsNullOrEmpty(control.Text))
                {
                    MessageBox.Show(control.Name + " Can not be empty");
                }
            }