Borkan
Borkan

Reputation: 29

Check All Controls If Empty And Make Exception For Some Controls

I want to check controls if they are empty and make exception for some Controls for example i want to make exception for these Textboxes Notes_txtbox and Job_txt . This is my function but it doesn't give me correct result . It gives Notes_txtbox,Job_txt are empty :

public bool Check_Inputs_Empty_Exception(List<Control> Exception_Control_List, 
                                         TableLayoutPanel TableLayoutPanel)
{
    bool is_empy = false;

    foreach (Control Control in TableLayoutPanel.Controls)
    {
        for (int i = 0; i < Exception_Control_List.Count; i++)
        {
            if (Control.Name != Exception_Control_List[i].Name && 
                Control.GetType() == Exception_Control_List[i].GetType())
                {
                    if (String.IsNullOrWhiteSpace(Control.Text))
                    {
                        MessageBox.Show(Control.Name + "  is empty");
                        is_empy = true;
                    }
                }
            }
        }

        return is_empy;
    }
}

And this is Function Call :

if (Check_Inputs_Empty_Exception(
      new List<Control> {Notes_txtbox,Job_txt}, TableLayoutPanel) == false)
{
    // My Add Function
}

Upvotes: 0

Views: 109

Answers (2)

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186748

I suggest using Linq instead of for and query the controls

// signature: more natural have "parent, excluded":
// "scan parent without excluded" 
// IEnumerable<Control> - now I can pass almost any collection, say array
public static bool Check_Inputs_Empty_Exception<T>(Control parent, 
                                                   IEnumerable<T> excluded) 
  where T : Control {

  if (null == parent)
    throw new ArgumentNullException(nameof(parent)); 

  // HashSet is more efficient (and convenient) for Contains then List 
  HashSet<T> exceptions = excluded == null 
    ? new HashSet<T>()
    : new HashSet<T>(excluded);

  // array of Controls of type T on parent with empty Text and not within exceptions
  var empty = parent
    .Controls
    .OfType<T>()
    .Where(control => !exceptions.Contains(control))
    .Where(control => string.IsNullOrEmpty(control.Text))
 // .OrderBy(control => control.Name)  //TODO: you may want to sort the controls
    .ToArray();

  foreach (T ctrl in empty)
    MessageBox.Show($"{ctrl.Name} is empty");

  return empty.Any();
}

// If we don't have controls to exclude
public static bool Check_Inputs_Empty_Exception<T>(Control parent) 
  where T : Control {
    return Check_Inputs_Empty_Exception<T>(parent, new T[0]);
}

usage

if (!Check_Inputs_Empty_Exception<TextBox>(TableLayoutPanel, 
                                           new TextBox[] {Notes_txtbox, Job_txt})) {

  //TODO: relevant code here
}

Edit: If you want to test, say, TextBoxs only (exclude all other Controls like Panels, Buttons) you can use generics

Upvotes: 2

John Wu
John Wu

Reputation: 52260

This is a simple and common logic flaw. Your loops are set up with the wrong logic gates. You are simply searching for any non-match, which you will always find (for every control in the control list there is a control in the exception list that is not the same control, unless the exception list has exactly one element).

Instead, search for any single match and set a flag if found. When the flag is set you move the outer loop on to the next iteration.

public bool Check_Inputs_Empty_Exception(List<Control> Exception_Control_List, TableLayoutPanel TableLayoutPanel)
{
    bool is_empy = false;

    foreach (Control Control in TableLayoutPanel.Controls)
    {
        bool found = false;
        for (int i = 0; i < Exception_Control_List.Count; i++)
        {
            if (Control == Exception_Control_List[i]) 
            {
                found = true;
                break;
            }
        }
        if (found) continue;
        if (String.IsNullOrWhiteSpace(Control.Text))
        {
            MessageBox.Show(Control.Name + "  is empty");
            is_empy = true;
        }
    }

    return is_empy;
}

With a little LINQ you can simplify this quite a bit too. Also, if you just want textboxes, you can filter out everything else using OfType<>().

public bool Check_Inputs_Empty_Exception(List<Control> Exception_Control_List, TableLayoutPanel TableLayoutPanel)
{
    bool result = false;

    var emptyTextboxes = TableLayoutPanel.Controls
       .OfType<TextBox>()
       .Where( c => string.IsNullOrEmpty(c.Text) )
       .ToList();

    foreach (var control in emptyTextboxes)
    {
        if (!Exception_Control_List.Any( c => c == control )) 
        {
            MessageBox.Show(control.Name + "  is empty");
            result = true;
        }
    }

    return result;
}

Upvotes: 2

Related Questions