How to get a simple but good form validation

I used to get the form validation by hand, with some ugly checks, message boxes, several boolean variables to combine with a lot of operators && and ||. A TOTAL mess.

My target was to provide a simple validation tool that I can spread (by inheritance) to all the forms in a project.
So if your project needs only a simple check for mandatory fields, the solution I found maybe can interest you. If you need something more sofisticated, you can imagine an extension of this solution to suite your needs.

How to get it

In a base form class, the parent of all my forms in the project, get an instance of an ErrorProvider, by putting it into the form. Be sure to have “Modifier” property set to “Protected”.
By default, the form property AutoValidate is set to EnablePreventFocusChange. This way, all the controls fire up Validating Event when it’s time to, and the focus will remain on the control when the validation fails.
In this base form we have to add two methods: ValidateControl and SetValidationHandlerOnControl.
The first one is the method that will handle the validation on the control we need to check.
The second one will add the validation handler to the control.

namespace ValidationTest{
  public partial class MyBaseForm 
  {
    ... 
    protected void ValidateControlHandler(object sender, CancelEventArgs e)
    {
      // this string will be the tooltip shown when an error appears
      String error = null;
      String textToCheck = String.Empty;
  
      // we need to be sure that the sender control is 
      // of the type System.TextBox
      Type senderType = sender.GetType();
      if (senderType == typeof(TextBox))
        textToCheck = ((TextBox)sender).Text;
      else 
        throw new ArgumentException(
  	    "The sender is not a TextBox, but a " + senderType.Name);
  
      // Mandatory field: if the textToCheck is null or empty, fire up the error 
      if (String.IsNullOrEmpty(textToCheck))
      {
        error = "Mandatory field"; 
        // this CancelEventArgs property locks the pointer over the control 
        // until the error disappears
        e.Cancel = true;
      }
  
      // if there isn't any error, the SetError get a 
      // null string and it will not shown.
      // otherwise the SetError will show an icon and a tooltip 
      // next to the control that fails the validation
      errorProvider.SetError((Control)sender, error);
    }
  
    protected void SetValidationHandlerOnControl(Control ctrl) 
    { 
      // we need to be sure that the sender control 
      // is of the type System.TextBox
      Type ctrlType = ctrl.GetType();
      if (ctrlType == typeof(TextBox))
        ctrl.Validating += new CancelEventHandler(this.ValidateControlHandler);
    }
  }
}

Ok, that’s almost done.
Now, if we had a form that inherits from MyBaseForm, we can add the controls we need to validate with a simple call to SetValidationHandlerOnControl.
Let’s consider that we have three TextBoxes: by default they all have property CausesValidation set to true. And let’s have a button that is the default AcceptButton for the form, with the TabIndex property value set to be greater than the TabIndex value of the textboxes.
So we need to call

namespace ValidationTest{
  public partial class MyChildForm : MyBaseForm
  {
    public MyChildForm(){
      InitializeComponent();
      SetValidationHandlerOnControl(this.textBox1);
      SetValidationHandlerOnControl(this.textBox2);
      SetValidationHandlerOnControl(this.textBox3);
    ...
    }
  }
}

that’s it!
Now if we don’t provide any string in one of the textBox, the ErrorProvider will show a little (!) icon near to the textBox, the focus will remain on until the string is null or empty. (See image below)
validation
Get the solution with this example here (18Kb). Hope you’ll find it interesting…
Comment out the article if you like it!

EDIT: corrected a typo. Sorry!

Singleton Pattern per C#

Singleton Pattern per C#

piccolo esempio di pattern singleton thread safe per C#. dal momento che lo uso molto spesso e che devo copiarmelo di qua e di là, ho deciso di scriverlo sul sito, che almeno so sempre dove trovarlo =D
ciao

public class Oggetto 
{
   #region Singleton
   //singleton pattern
   private static bool _isInit;
   private static Exception _error;
   private static volatile Oggetto _instance = null;
   private static object _syncObj = new object();

   /// 
   /// Get the Oggetto Instance
   /// 
   public static Oggetto Instance
   {
      get
        {
           if (_instance == null)
           {
              lock (_syncObj)
	      {
                 if (_instance == null)
                    _instance = new Oggetto();
              }
           }
           if (_isInit)
              return _instance;
           else
              throw new Exception(
                 "Error initializing Oggetto", _error);
        }
   }

   private Oggetto()
   {
      try
      {
         InitData();
         _isInit = true;
      }
      catch (Exception ex)
      {
         _isInit = false;
	 _error = ex;
      }
   }
   #endregion

   private void InitData()
   {
      // qua ci va l'inizializzazione
   }

   // comodo per reinizializzare tutto, se serve
   internal void RefreshCache()
   {
      this.InitData();
   }
}

c#, dotnet, lavoro, pattern, singleton, best practices

come chiudersi fuori da soli…

stamattina ho fatto il mio primo danno. sto lavorando sul mio schema di database in un’istanza di oracle. il mio user ha grant di administer database trigger perchè ho bisogno di creare un logon trigger del tipo

create or replace trigger user_logon_trigger 
    after logon on database
begin
  my_package.do_something();
end;

Insomma ricreo lo schema (trigger compreso), faccio logout-login. Non va, non riesco ad entrare.
Nel frattempo non si collegano nemmeno i miei tre colleghi, che aspettano di lavorare su altri schemi sulla stessa istanza. Il trigger sembra invalido, e caccia fuori tutti gli utenti.
Non vi dico i casini per recuperare il DBA, che non riusciva nemmeno lui a loggarsi, e alla fine fare un reboot della macchina.
Stavolta, il DBA fa riavviare il db modificando in init.ora la variabile

_system_trig_enabled = false

che permette di far partire il db senza trigger. bon. riabilitiamo il trigger e vediamo se tutto gira. Sì, gira tutto.
Tempo 5 minuti ed è di nuovo tutto TFU (Totally Fucked Up come dice il mio omonimo).
Alla fine si svela l’arcano: nel pacchetto my_package ho lasciato un dbms_pipe.send_message() che mi serviva per debug. Questa simpatica utility va a scrivere in un buffer i messaggi. Ma se il buffer non viene “svuotato” leggendolo, il buffer si riempie. E riempie la memoria dell’istanza oracle. Non sapete quanto… finchè implode tutto e non si riesce nemmeno a collegarsi…
Quindi, oggi ho imparato che: si può escludere l’attivazione di un trigger per un determinato utente:

create or replace trigger user_logon trigger
  after logon on database when user not in ('sys', 'system', 'pippo')
begin
  ...
end;  

Poi ho imparato che è meglio tenersi amico il DBA.
e che le cose di debug si fanno sull’istanza di debug.
e che dbms_pipe è una mer@a.