Click here to Skip to main content
15,896,500 members
Articles / Programming Languages / C#

SourceGrid - Open Source C# Grid Control

Rate me:
Please Sign up or sign in to vote.
4.94/5 (429 votes)
4 Aug 2013MIT24 min read 5M   23.7K   1K  
SourceGrid is a free open source grid control. Supports virtual grid, custom cells and editors, advanced formatting options and many others features
using System;
using System.Windows.Forms;

namespace SourceGrid.Models
{
	public abstract class EditorControlBase : ModelBase
	{
		public EditorControlBase()
		{
			EnableEdit = true;
		}

//		private Grid m_Grid = null;
//		/// <summary>
//		/// The grid where the CellEditor is linked
//		/// </summary>
//		public Grid Grid
//		{
//			get{return m_Grid;}
//		}


		/// <summary>
		/// Control used when editing a cell
		/// </summary>
		private System.Windows.Forms.Control m_EditControl;
		/// <summary>
		/// Control used when editing a cell. Can throw an Exception if the control is not attached to the grid, use IsAttached to check and AttachEditorControl to force the control to attach to the grid.
		/// </summary>
		public System.Windows.Forms.Control EditControl
		{
			get
			{
				if (m_EditControl==null)
					throw new ApplicationException("Editor not attached to the grid, call AttachEditorControl first");
				return m_EditControl;
			}
/*			set
			{
				//remove the control if this is already attached to the grid
				RemoveFromGrid();
				m_EditControl = value;
			}*/
		}


		/// <summary>
		/// Start editing the cell passed
		/// </summary>
		/// <param name="p_Cell">Cell to start edit</param>
		/// <param name="p_StartEditValue">Can be null(in this case use the p_cell.Value</param>
		public override void StartEdit(Cell p_Cell, object p_StartEditValue)
		{
			if (IsEditing == false && EnableEdit)
			{
				//verifico di non avere ancora una cella associata
				if (EditCell!=null)
					throw new ApplicationException("There is already a Cell in edit state");
//				if (m_EditControl == null)
//					throw new ApplicationException("No control loaded for this editor");
				if (p_Cell==null)
					throw new ArgumentNullException("p_Cell");
				if (p_Cell.Grid == null)
					throw new ApplicationException("Cell is not bounded to a grid");

				//if (m_Grid!=p_Cell.Grid)
				AttachEditorControl(p_Cell.Grid);

				m_EditControl.Location = p_Cell.DisplayRectangle.Location; 
				m_EditControl.Size = p_Cell.DisplayRectangle.Size;

				m_EditControl.Show();
				m_EditControl.BringToFront();
				m_EditControl.Focus();
				SetEditCell(p_Cell);//con questa chiamata inizia logicamente l'edit
			}
		}

		/// <summary>
		/// Returns the GUID of the control that the current editor use
		/// </summary>
		/// <returns></returns>
		private Guid m_Guid = Guid.NewGuid();//create a new key for each instance of the class
		public virtual Guid GetEditorControlGuid()
		{
			return m_Guid;
		}
		/// <summary>
		/// Create a new control used in this editor
		/// </summary>
		/// <returns></returns>
		public abstract Control CreateEditorControl();


		/// <summary>
		/// Apply edited value
		/// </summary>
		/// <returns></returns>
		public override bool ApplyEdit()
		{
			if (IsEditing == true && EnableEdit == true)
			{
				bool l_bSuccess;

				l_bSuccess = SetCellValue(EditCell, GetEditedValue());

				return l_bSuccess;
			}
			else
				return true;
		}
		/// <summary>
		/// Terminate the edit action
		/// </summary>
		/// <param name="p_Cancel">True to cancel the editing and return to normal mode, false to call automatically ApplyEdit and terminate editing</param>
		/// <returns>Returns true if the cell terminate the editing mode</returns>
		public override bool EndEdit(bool p_Cancel)
		{
			if (IsEditing == true)
			{
				bool l_bSuccess = true;
				if (p_Cancel==false)
					l_bSuccess = ApplyEdit();

				if (l_bSuccess)
				{
					Grid l_Grid = EditCell.Grid;
					//di fatto mettendo questa property a null termina logicamente l'edit
					// e � importante che venga fatto appena possibile
					SetEditCell(null);

					if (l_Grid!=null)
						l_Grid.SetFocusOnCellsContainer(); //TODO da verificare che questo non comporti altre chiamate 
					if (m_EditControl!=null)
						m_EditControl.Hide();
				}

				return l_bSuccess;
			}
			else
				return true;
		}


		//ATTENZIONE: Ho dovuto fare un sistema di chiavi per i controlli dell'edit perch� altrimenti non riuscivo a fare uno share corretto degli editor.
		// questo perch� se ad esempio aggiungo un controllo di edito a una griglia e questa griglia viene distrutta, viene chiamato il
		// dispose su tutti gli oggetti contenuti, questo di fatto distruggeva l'editor che invece era magari condiviso da pi� griglie

		/// <summary>
		/// Returns true if the control is atteched to the grid.
		/// </summary>
		/// <returns></returns>
		public virtual bool IsAttached()
		{
			if (m_EditControl==null)
				return false;
			else
				return true;
		}

		/// <summary>
		/// Add the current editor to the grid controls
		/// </summary>
		/// <param name="p_Grid"></param>
		public virtual void AttachEditorControl(Grid p_Grid)
		{
			if (p_Grid.ControlsRepository.ContainsKey(GetEditorControlGuid()) == false)
			{
				m_EditControl = CreateEditorControl();
				p_Grid.ControlsRepository.Add(GetEditorControlGuid(), m_EditControl);

				//m_Control.KeyDown += new KeyEventHandler(InnerControl_KeyDown);
				m_EditControl.Validating += new System.ComponentModel.CancelEventHandler(InnerControl_Validating);
				m_EditControl.Validated += new EventHandler(InnerControl_Validated);

				m_EditControl.Hide();
			}
		}

		/// <summary>
		/// Remove the current editor from the grid control
		/// </summary>
		/// <param name="p_Grid"></param>
		public virtual void DetachEditorControl(Grid p_Grid)
		{
			if (p_Grid.ControlsRepository.ContainsKey(GetEditorControlGuid()))
			{
				if (m_EditControl == null)
					throw new ArgumentNullException("m_EditorControl");

				//m_Control.KeyDown -= new KeyEventHandler(InnerControl_KeyDown);
				m_EditControl.Validating -= new System.ComponentModel.CancelEventHandler(InnerControl_Validating);
				m_EditControl.Validated -= new EventHandler(InnerControl_Validated);
					
				//.Net bug : application doesn't close when a active control is removed from the control collection
				// change the focus first
				p_Grid.SetFocusOnCellsContainer();

				m_EditControl.Hide();
				p_Grid.ControlsRepository.Remove(GetEditorControlGuid());
			}
			m_EditControl = null;
		}


		protected virtual void InnerControl_Validated(object sender, EventArgs e)
		{
			try
			{
				if (IsEditing)
					EndEdit(false);
			}
			catch(Exception)
			{
				//TODO da rivedere
				System.Diagnostics.Debug.Assert(false);
			}
		}
		protected virtual void InnerControl_Validating(object sender, System.ComponentModel.CancelEventArgs e)
		{
			try
			{
				if (IsEditing)
				{
					ValidatingEventArgs l_cancelEvent = new ValidatingEventArgs(GetEditedValue());
					OnValidatingValue(l_cancelEvent);

					e.Cancel = l_cancelEvent.Cancel;
				}
			}
			catch(Exception)
			{
				e.Cancel = true;
			}
		}

		public override abstract object GetEditedValue();
	}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer
Italy Italy
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions