/// <summary>
		/// Bind datasource and refresh display of rows in the DataGridView.
        /// Also attempts to save some settings for each subsequent Bind call.
		/// </summary>
		public void Bind()
		{
            int iCurrRow = 0;
            try
            {
                // Save the current Row index
                iCurrRow = this.dataGridView1.CurrentRow.Index;
                // Save our Column widths
                for (int i = 0; i < this.asGridHeaders.Length; i++)
                    this.aiGridColWidths[i] = this.dataGridView1.Columns[i].Width;
            }
            catch
            {
            }

			try
			{
				// Reset the DataSet and assign as the data source..
				this.dsGrid.Clear();

				if (TableHelper.FillDataSet(this.dsGrid, this.sGridTable, this.asGridColumns, this.sGridOrderBy, this.sGridWhere))
				{
					// Set row filter if applicable
                    if (this.sGridFilter != string.Empty)
                        this.dsGrid.Tables[0].DefaultView.RowFilter = this.sGridFilter;
                    else
                        this.dsGrid.Tables[0].DefaultView.RowFilter = null;

					// Bind data source
					this.dataGridView1.DataSource = this.dsGrid.Tables[0].DefaultView;
				}

				// Set Column header and format
				for (int i = 0; i < this.asGridHeaders.Length; i++)
				{
					this.dataGridView1.Columns[i].HeaderText = this.asGridHeaders[i];
                    if (this.dataGridView1.Columns[i].ValueType.ToString().Contains("DateTime"))
                        this.dataGridView1.Columns[i].DefaultCellStyle.Format = "dd/MM/yyyy";
				}

                // Set Column widths (NB: width=0 will hide a column)
                if (this.bUseDefaultColumnWidths)
                {
                    this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
                }
                else
                {
                    for (int i = 0; i < this.aiGridColWidths.Length; i++)
                        this.dataGridView1.Columns[i].Width = this.aiGridColWidths[i];
                }
                
                // Set internal rowcount
				this.iGridRowCount = this.dsGrid.Tables[0].DefaultView.Count;

				// Set Alternate grid row Color
                this.dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = sbDataGridControlConfig.ColorActual;

                // Set Binding Navigator data source
                BindingSource bs = new BindingSource();
                bs.DataSource = this.dataGridView1.DataSource;
                this.bindingNavigator1.BindingSource = bs;
                
                // Refresh the grid
				this.dataGridView1.Refresh();

				// Select initial row and let them know we're navigating..
				if (this.iGridRowCount > 0)
				{
                    if (iCurrRow < this.iGridRowCount)
                    {
                        // Restore our current position
                        this.dataGridView1.Rows[iCurrRow].Selected = true;
                        this.dataGridView1.CurrentCell = this.dataGridView1.Rows[iCurrRow].Cells[0];
                    }
                    else
                    {
                        // Select the first row as default
                        this.dataGridView1.Rows[0].Selected = true;
                        this.dataGridView1.CurrentCell = this.dataGridView1.Rows[0].Cells[0];
                    }
					this.NavigateClickEvent(this.dataGridView1.CurrentRow);
				}
			}
			catch (Exception ex)
			{
				FormErrorHandler eHandler = new FormErrorHandler(ex);
				eHandler.ShowDialog();
			}
		}
		/// <summary>
        /// Authenticate access using Login Name (NO PASSWORD).
		/// </summary>
		/// <param name="sLogin"></param>
		/// <returns></returns>
        private bool AuthenticateNoPassword(string sLogin)
		{
			bool bAuthenticated = false;
            string sResponse = string.Empty;
            try
            {
                sResponse = TableHelper.GetScalar("tSysUser", "LoginID", "(LoginID = '" + sLogin + "') AND (IsCurrent = 'Y')");
                if ((sResponse != string.Empty) & (sResponse == sLogin))
                {
                    bAuthenticated = true;
                }
            }
            catch (Exception ex)
            {
                FormErrorHandler frmError = new FormErrorHandler(ex);
                frmError.Show();
            }
            return bAuthenticated;
		}
		/// <summary>
		/// Add a new user.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
        private void btnAdd_Click(object sender, System.EventArgs e)
		{
			string sLogin = this.tbName.Text.Trim();

            // Check for empty user Login ID
			if (sLogin == string.Empty)
			{
				MessageBox.Show("Please enter a valid non-empty Login ID.",
					"Invalid Login ID",
					MessageBoxButtons.OK,
					MessageBoxIcon.Error);
                return;
			}

            // Check for existence of non-alphanumeric characters
            if (!this.IsAlphaNumeric(sLogin))
            {
                MessageBox.Show("Login ID must contain alphanumeric characters only (no punctuation or spaces).",
                    "Invalid Login ID",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                return;
            }
            
            // Check for existence of this Login ID
            int iCheck = TableHelper.Count("tSysUser", "LoginID = '" + sLogin + "'");
            if (iCheck > 0)
            {
                MessageBox.Show("Login ID " + sLogin + " is already in use. Please try again.",
                    "Login ID Exists",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                return;
            }

			// Set default Login hash (combination of Login ID and Login ID in lower case..
			string sHash = FormsAuthentication.HashPasswordForStoringInConfigFile(sLogin + sLogin.ToLower(),
                PASSWORD_HASH_ALGORITHM);

			string[] asCol = {"LoginID", "LoginHash"};
			string[] asVal = {"'" + sLogin.Replace("'", "''") + "'", "'" + sHash + "'" };
            bool bSuccess = false;
            try
            {
                // Insert row
                bSuccess = TableHelper.Insert("tSysUser", asCol, asVal);
                if (bSuccess)
                    this.DialogResult = DialogResult.OK;

                // Determine primary key of the new User row
                string sPKuser = TableHelper.GetScalar("tSysUser", "PKUserID", "LoginHash = '" + sHash + "'");

                // Determine lowest level role and assign to new user
                int iMinAccess = Convert.ToInt32(TableHelper.Min("tSysRole", "RoleAccessLevel"));
                string sPKrole = TableHelper.GetScalar("tSysRole", "PKRoleID", "RoleAccessLevel = " + iMinAccess.ToString());
				string[] asColr = {"FKUserID", "FKRoleID"};
    			string[] asValr = {sPKuser, sPKrole};
                TableHelper.Insert("tSysUserRoles", asColr, asValr);
            }
            catch (Exception ex)
            {
                FormErrorHandler eHandler = new FormErrorHandler(ex);
                eHandler.ShowDialog();
            }

            // Close window
			this.Close();
		}
		/// <summary>
        /// Authenticate access using both Login Name and (hashed) Password.
		/// </summary>
		/// <param name="sLogin"></param>
		/// <param name="sHash"></param>
		/// <returns></returns>
        private bool AuthenticatePassword(string sLogin, string sHash)
		{
			bool bAuthenticated = false;
            string sDBHash = string.Empty;
            try
            {
                sDBHash = TableHelper.GetScalar("tSysUser", "LoginHash", "(LoginID = '" + sLogin + "') AND (IsCurrent = 'Y')");

                //debug
                //MessageBox.Show(sHash, "Hash from Login", MessageBoxButtons.OK, MessageBoxIcon.Information);
                //MessageBox.Show(sDBHash, "Hash from DB", MessageBoxButtons.OK, MessageBoxIcon.Information);
                //debug

                if ((sDBHash != string.Empty) & (sDBHash == sHash))
                {
                    bAuthenticated = true;
                }
            }
            catch (Exception ex)
            {
                FormErrorHandler frmError = new FormErrorHandler(ex);
                frmError.Show();
            }
            return bAuthenticated;
		}