Skip to content

Instantly share code, notes, and snippets.

@hanssens
Created May 31, 2011 06:47
Show Gist options
  • Save hanssens/1000075 to your computer and use it in GitHub Desktop.
Save hanssens/1000075 to your computer and use it in GitHub Desktop.
AdresValidator - WinForms Component voor Cendris adres validatie
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using Securancy.Common;
namespace WindowsApplication1
{
public delegate void OnValidatedHandler(object sender, EventArgs e);
public delegate void OnValidatingHandler(object sender, EventArgs e);
/// <summary>
/// Valideert een Postcode- en Huisnummer control tegen de Cendris webservice.
/// </summary>
/// <remarks>
/// Het AdresValidator component is vrij simpel van opzet. Koppel de velden
/// <strong>HuisnummerControl</strong> en <strong>PostcodeControl</strong> aan
/// een willekeurige System.Windows.Forms.Control met .Text-property en deze
/// valideert de rest automatisch.
/// <br /><br />
/// Daarnaast zijn er nog enkele nifty features ingebakken, zoals
/// <strong>AutoErrorProvider</strong>, <strong>AutoValidation</strong> en
/// de event <strong>OnValidated</strong> waarmee je meer controle hebt over
/// diverse bewerkingen als je dit wilt.
/// </remarks>
public class AdresValidator : Component
{
#region -- Constructor & Class Dependencies --
/// <summary>
/// Required designer variable.
/// </summary>
private Container components = null;
/// <summary>
/// Initialiseert een nieuwe instantie van de AdresValidator class.
/// </summary>
/// <param name="container"></param>
public AdresValidator(System.ComponentModel.IContainer container)
{
container.Add(this);
InitializeComponent();
}
/// <summary>
/// Initialiseert een nieuwe instantie van de AdresValidator class.
/// </summary>
public AdresValidator()
{
InitializeComponent();
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
/// <summary>
/// Vuilnisman.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
#endregion
#region -- Private Fields/Objects --
private ErrorProvider errProvPostcode = new ErrorProvider();
private ErrorProvider errProvHuisnummer = new ErrorProvider();
private bool HasChanged = false;
#endregion
#region -- Functionele Properties --
private bool _AutoErrorProvider = true;
/// <summary>
/// Bepaalt of de control bij een niet succesvolle validatie automatisch een ErrorProvider genereert.
/// </summary>
/// <remarks>
/// De standaardwaarde hiervoor is <strong>AutoErrorProvider = true</strong>, waarmee automatisch een
/// validatie uitgevoerd wordt bij het verlaten van de PostcodeControl en het HuisnummerControl.
/// <br /><br />
/// Bij <strong>IsValid = false</strong> wordt de ErrorProvider in dit geval getoond.
/// </remarks>
[Category("Properties")]
[Description("Automatisch een ErrorProvider weergeven bij fouten.")]
public bool AutoErrorProvider
{
get { return _AutoErrorProvider; }
set { _AutoErrorProvider = value; }
}
private bool _AutoShowMessageBox = true;
/// <summary>
/// Bepaalt of de control automatisch een MessageBox genereert bij een foutieve validatie.
/// </summary>
[Category("Properties")]
[Description("Automatisch een MessageBox weergeven bij fouten.")]
public bool AutoShowMessageBox
{
get { return _AutoShowMessageBox; }
set { _AutoShowMessageBox = value; }
}
private bool _AutoValidation = true;
/// <summary>
/// Automatisch valideren inschakelen wanneer de tekst van Postcode en Huisnummer wijzigt.
/// </summary>
/// <remarks>
/// Bij <strong>AutoValidation = true</strong> (standaard) valideert het component automatisch
/// of de Text binnen de PostcodeControl en HuisnummerControl geldig zijn. Het component doet
/// dit door via de webservice de <strong>RetrieveAddress()</strong> webmethod aan te roepen.
/// <br /><br />
/// Na een validatie, automatisch of niet, kan altijd nog een actie ondernomen worden. Stel we
/// willen bij een validatie textboxes enablen bij <strong>AdresValidator.IsValid</strong> of
/// disablen wanneer dit op 'false' staat. In dit geval kunnen we inhaken op de
/// <strong>OnValidation</strong>-event en veel informatie uit het component zelf halen.
/// </remarks>
[Category("Properties")]
[Description("Automatisch valideren inschakelen wanneer de tekst van Postcode en Huisnummer wijzigt.")]
public bool AutoValidation
{
get { return _AutoValidation = true; }
set { _AutoValidation = value; }
}
private bool _Enabled = true;
/// <summary>
/// Validatie van het component inschakelen.
/// </summary>
[Category("Properties")]
[Description("Validatie van het component inschakelen.")]
public bool Enabled
{
get { return _Enabled = true; }
set { _Enabled = value; }
}
private bool? _IsValid;
/// <summary>
/// Nullable read-only waarde of de control succesvol is gevalideerd.
/// Bij 'Null' is de control nog niet gevalideerd.
/// </summary>
[Category("Properties")]
[Description("Nullable read-only waarde of de control succesvol is gevalideerd. Bij 'Null' is de control nog niet gevalideerd.")]
public bool? IsValid
{
get
{
return _IsValid;
}
}
#endregion
#region -- Embedded Controls --
private Control _PostcodeControl;
/// <summary>
/// Bepaalt welke control de postcode in diens .Text-parameter bevat.
/// </summary>
[Category("ControlBinding")]
[Description("Bepaalt welke control de postcode in diens .Text-parameter bevat.")]
public Control PostcodeControl
{
get { return _PostcodeControl; }
set
{
// Embed de control:
_PostcodeControl = value;
// Bij iedere textuele wijziging wordt dit event aangeroepen:
this.PostcodeControl.TextChanged += new EventHandler(TextChanged);
// Enkel bij "AutoValidation = True" gaan we automatisch valideren:
if (AutoValidation == true)
{
this.PostcodeControl.Leave += new EventHandler(TextLeave);
}
}
}
private Control _HuisnummerControl;
/// <summary>
/// Bepaalt welke control het huisnummer in diens .Text-parameter bevat.
/// </summary>
[Category("ControlBinding")]
[Description("Bepaalt welke control het huisnummer in diens .Text-parameter bevat.")]
public Control HuisnummerControl
{
get { return _HuisnummerControl; }
set
{
// Embed de control:
_HuisnummerControl = value;
// Bij iedere textuele wijziging wordt dit event aangeroepen:
this.HuisnummerControl.TextChanged +=new EventHandler(TextChanged);
// Enkel bij "AutoValidation = True" gaan we automatisch valideren:
if (AutoValidation == true)
{
this.HuisnummerControl.Leave += new EventHandler(TextLeave);
}
}
}
#endregion
#region -- Webservice ReturnValues (read-only) --
private string _Huisnummer;
/// <summary>
/// Read-only retourwaarde vanuit de webservice, na een succesvolle validatie.
/// </summary>
[Category("ReturnValues")]
[Description("Read-only retourwaarde vanuit de webservice, na een succesvolle validatie.")]
public string Huisnummer
{
get { return _Huisnummer; }
}
private string _Postcode;
/// <summary>
/// Read-only retourwaarde vanuit de webservice, na een succesvolle validatie.
/// </summary>
[Category("ReturnValues")]
[Description("Read-only retourwaarde vanuit de webservice, na een succesvolle validatie.")]
public string Postcode
{
get { return _Postcode; }
}
private string _Straatnaam;
/// <summary>
/// Read-only retourwaarde vanuit de webservice, na een succesvolle validatie.
/// </summary>
[Category("ReturnValues")]
[Description("Read-only retourwaarde vanuit de webservice, na een succesvolle validatie.")]
public string Straatnaam
{
get { return _Straatnaam; }
}
private string _Woonplaats;
/// <summary>
/// Read-only retourwaarde vanuit de webservice, na een succesvolle validatie.
/// </summary>
[Category("ReturnValues")]
[Description("Read-only retourwaarde vanuit de webservice, na een succesvolle validatie.")]
public string Woonplaats
{
get { return _Woonplaats; }
}
#endregion
#region -- Events en EventHandlers --
/// <summary>
/// Overriding handler voor Postcode- en Huisnummer wanneer de gebruiker het veld verlaat.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// Via deze private method worden de Control_Leave()-events voor de embedded controls overridden.
/// <br /><br />
/// Indien je zelf toch zelf de handlers nodig hebt dan kun je de <strong>AutoValidate = false</strong>
/// gebruiken en zelf de <strong>Validate()</strong> methode aanroepen. Het component zal dan
/// vervolgens niet meer inhaken op deze events.
/// </remarks>
void TextLeave(object sender, EventArgs e)
{
Validate();
}
/// <summary>
/// Overriding handler voor Postcode- en Huisnummer wanneer de tekst wijzigt.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// Via deze private method worden de Control_TextChanged()-events voor de embedded controls overridden.
/// <br /><br />
/// Het enige doel hiervan is de <strong>functionele eis</strong> dat er enkel validatie plaats vindt
/// wanneer de tekst is gewijzigd.
/// </remarks>
void TextChanged(object sender, EventArgs e)
{
// Wanneer de inhoud van een TextBox wijzigt zetten we deze flag aan.
// Deze wordt na validatie vervolgens weer op 'false' gezet:
this.HasChanged = true;
}
/// <summary>
/// Wordt aangeroepen nadat validatie is voltooid.
/// </summary>
/// <remarks>
/// Nadat een validatie is doorlopen kunnen we via de <strong>IsValid</strong>-parameter
/// en de diverse read-only parameters de juiste waarden uitlezen die we terug hebben
/// gehad via de webservice.
/// </remarks>
/// <example>
/// Hieronder een voorbeeld voor de implementatie van dit event.
/// <br /><br />
/// private void AdresValidator1_OnValidated(object sender, EventArgs e)<br />
/// {<br />
/// if (AdresValidator1.IsValid) {<br />
/// Console.WriteLine("Straatnaam: " + AdresValidator1.Straatnaam);<br />
/// Console.WriteLine("Huisnummer: " + AdresValidator1.Straatnaam);<br />
/// Console.WriteLine("Postcode: " + AdresValidator1.Straatnaam);<br />
/// Console.WriteLine("Woonplaats: " + AdresValidator1.Straatnaam);<br />
/// Console.ReadLine();<br />
/// }<br />
/// else {<br />
/// MessageBox.Show("Validatie is niet succesvol!");<br />
/// }<br />
/// }<br />
/// <br />Tip van de dag:
/// natuurlijk is dit event ideaal om eventuele andere controls, zoals
/// een TextBox met straatnaam en woonplaats, te vullen, enablen of disablen. <br />
/// </example>
[Description("Wordt aangeroepen nadat validatie is voltooid.")]
public event OnValidatedHandler OnValidated;
protected virtual void OnValidation(EventArgs e)
{
if (OnValidated != null) { OnValidated(this, e); }
}
/// <summary>
/// Wordt aangeroepen voor validatie.
/// </summary>
[Description("Wordt aangeroepen voor validatie.")]
public event OnValidatingHandler OnValidating;
protected virtual void OnValidate(EventArgs e)
{
if (OnValidating != null) { OnValidating(this, e); }
}
#endregion
/// <summary>
/// Valideert het component.
/// </summary>
/// <returns>Valideert het component.</returns>
/// <remarks>
/// Wanneer <strong>Enabled = true</strong> wordt deze method automatisch aangeroepen bij
/// het <i>Leave</i>-event van de onderliggende controls (PostcodeControl en HuisnummerControl).
/// <br /><br />
/// Met andere woorden: hier gebeurt de magic! :)
/// <br /><br />
/// </remarks>
public void Validate()
{
// Controleer of we wel moeten valideren, zo nee dan abort:
if (this.Enabled == false) { return; }
// Controleer of er wel iets gewijzigd is, anders zonde van de moeite:
if (this.HasChanged == false) { return; }
// Roep voor verdere Validatie eerst de event 'OnValidating' aan:
this.OnValidate(new EventArgs());
// Controleer of de vereiste velden zijn ingevuld:
if (String.IsNullOrEmpty(PostcodeControl.Text) || String.IsNullOrEmpty(HuisnummerControl.Text))
{
// Als een van de velden niet ingevuld is dan markeren we de 'IsValid'-property als zijnde "niet gechecked".
this._IsValid = null;
return;
}
// Roep de webservice aan en haal het juiste adres op (if any):
WsPostcode cendrisAdres = Securancy.Interop.Cendris.RetrieveAddress(PostcodeControl.Text, HuisnummerControl.Text);
if (cendrisAdres != null)
{
// All is well:
this._Huisnummer = HuisnummerControl.Text;
this._Postcode = PostcodeControl.Text.ToUpper().Replace(" ", String.Empty);
this._Straatnaam = cendrisAdres.Straatnaam;
this._Woonplaats = cendrisAdres.Woonplaats;
this._IsValid = true;
}
else
{
// Nee, er is iets niet goed:
this._IsValid = false;
this._Huisnummer = String.Empty;
this._Postcode = String.Empty;
this._Straatnaam = String.Empty;
this._Woonplaats = String.Empty;
}
// Bepaal of we automatisch een ErrorProvider moeten tonen bij een *niet* succesvolle validatie:
if (AutoErrorProvider == true && this.IsValid == false)
{
errProvPostcode.SetIconAlignment(this.PostcodeControl, ErrorIconAlignment.MiddleRight);
errProvPostcode.SetIconPadding(this.PostcodeControl, 3);
errProvPostcode.SetError(this.PostcodeControl, "Ongeldige postcode/huisnummer combinatie.");
errProvHuisnummer.SetIconAlignment(this.HuisnummerControl, ErrorIconAlignment.MiddleRight);
errProvHuisnummer.SetIconPadding(this.HuisnummerControl, 3);
errProvHuisnummer.SetError(this.HuisnummerControl, "Ongeldige postcode/huisnummer combinatie.");
}
else
{
errProvHuisnummer.Clear();
errProvPostcode.Clear();
}
// Bepaal of we automatisch een MessageBox genereren:
if (AutoShowMessageBox == true && this.IsValid == false)
{
// Deze functie o.v.v. Jacqueline geïmplementeerd:
if (MessageBox.Show("Ongeldige of onbekende postcode/huisnummer combinatie.\n\nWeet u zeker dat u deze waarden wilt gebruiken?", "Validatie", MessageBoxButtons.YesNo, MessageBoxIcon.Error) != DialogResult.Yes)
{
// nee, de gebruiker wilt dit corrigeren:
HuisnummerControl.Text = String.Empty;
PostcodeControl.Text = String.Empty;
PostcodeControl.Focus();
}
}
// Na validatie kunnen we de 'changed' flag aanpassen (zie ook event TextChanged):
this.HasChanged = false;
// Tot slot, de - te overriden - event handler 'OnValidated' aanroepen:
this.OnValidation(new EventArgs());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment