Click here to Skip to main content
15,896,111 members
Articles / Multimedia / GDI

XPTable - .NET ListView meets Java's JTable

Rate me:
Please Sign up or sign in to vote.
4.97/5 (445 votes)
17 Sep 200512 min read 6.8M   55.3K   888  
A fully customisable ListView style control based on Java's JTable.
/*
 * Copyright � 2005, Mathew Hall
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 *    - Redistributions of source code must retain the above copyright notice, 
 *      this list of conditions and the following disclaimer.
 * 
 *    - Redistributions in binary form must reproduce the above copyright notice, 
 *      this list of conditions and the following disclaimer in the documentation 
 *      and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE.
 */


using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

using XPTable.Events;
using XPTable.Models.Design;
using XPTable.Renderers;


namespace XPTable.Models
{
	/// <summary>
	/// Represents a Cell that is displayed in a Table
	/// </summary>
	[DesignTimeVisible(true),
	TypeConverter(typeof(CellConverter))]
	public class Cell : IDisposable
	{
		#region EventHandlers

		/// <summary>
		/// Occurs when the value of a Cells property changes
		/// </summary>
		public event CellEventHandler PropertyChanged;

		#endregion


		#region Class Data

		// Cell state flags
		private static readonly int STATE_EDITABLE = 1;
		private static readonly int STATE_ENABLED = 2;
		private static readonly int STATE_SELECTED = 4;

		/// <summary>
		/// The text displayed in the Cell
		/// </summary>
		private string text;

		/// <summary>
		/// An object that contains data to be displayed in the Cell
		/// </summary>
		private object data;

		/// <summary>
		/// An object that contains data about the Cell
		/// </summary>
		private object tag;

		/// <summary>
		/// Stores information used by CellRenderers to record the current 
		/// state of the Cell
		/// </summary>
		private object rendererData;

		/// <summary>
		/// The Row that the Cell belongs to
		/// </summary>
		private Row row;

		/// <summary>
		/// The index of the Cell
		/// </summary>
		private int index;

		/// <summary>
		/// Contains the current state of the the Cell
		/// </summary>
		private byte state;
		
		/// <summary>
		/// The Cells CellStyle settings
		/// </summary>
		private CellStyle cellStyle;

		/// <summary>
		/// The Cells CellCheckStyle settings
		/// </summary>
		private CellCheckStyle checkStyle;

		/// <summary>
		/// The Cells CellImageStyle settings
		/// </summary>
		private CellImageStyle imageStyle;

		/// <summary>
		/// The text displayed in the Cells tooltip
		/// </summary>
		private string tooltipText;

		/// <summary>
		/// Specifies whether the Cell has been disposed
		/// </summary>
		private bool disposed = false;

		#endregion


		#region Constructor
		
		/// <summary>
		/// Initializes a new instance of the Cell class with default settings
		/// </summary>
		public Cell() : base()
		{
			this.Init();
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		public Cell(string text)
		{	
			this.Init();

			this.text = text;
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified object
		/// </summary>
		/// <param name="value">The object displayed in the Cell</param>
		public Cell(object value)
		{
			this.Init();

			this.data = value;
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text 
		/// and object
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="value">The object displayed in the Cell</param>
		public Cell(string text, object value)
		{
			this.Init();

			this.text = text;
			this.data = value;
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text 
		/// and check value
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="check">Specifies whether the Cell is Checked</param>
		public Cell(string text, bool check)
		{
			this.Init();

			this.text = text;
			this.Checked = check;
		}
		
		
		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text 
		/// and Image value
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="image">The Image displayed in the Cell</param>
		public Cell(string text, Image image)
		{
			this.Init();

			this.text = text;
			this.Image = image;
		}
		
		
		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text, 
		/// fore Color, back Color and Font
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="foreColor">The foreground Color of the Cell</param>
		/// <param name="backColor">The background Color of the Cell</param>
		/// <param name="font">The Font used to draw the text in the Cell</param>
		public Cell(string text, Color foreColor, Color backColor, Font font)
		{
			this.Init();

			this.text = text;
			this.ForeColor = foreColor;
			this.BackColor = backColor;
			this.Font = font;
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text 
		/// and CellStyle
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="cellStyle">A CellStyle that specifies the visual appearance 
		/// of the Cell</param>
		public Cell(string text, CellStyle cellStyle)
		{
			this.Init();

			this.text = text;
			this.cellStyle = cellStyle;
		}
		
		
		/// <summary>
		/// Initializes a new instance of the Cell class with the specified object, 
		/// fore Color, back Color and Font
		/// </summary>
		/// <param name="value">The object displayed in the Cell</param>
		/// <param name="foreColor">The foreground Color of the Cell</param>
		/// <param name="backColor">The background Color of the Cell</param>
		/// <param name="font">The Font used to draw the text in the Cell</param>
		public Cell(object value, Color foreColor, Color backColor, Font font)
		{
			this.Init();

			this.data = value;
			this.ForeColor = foreColor;
			this.BackColor = backColor;
			this.Font = font;
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text 
		/// and CellStyle
		/// </summary>
		/// <param name="value">The object displayed in the Cell</param>
		/// <param name="cellStyle">A CellStyle that specifies the visual appearance 
		/// of the Cell</param>
		public Cell(object value, CellStyle cellStyle)
		{
			this.Init();

			this.data = value;
			this.cellStyle = cellStyle;
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text, 
		/// object, fore Color, back Color and Font
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="value">The object displayed in the Cell</param>
		/// <param name="foreColor">The foreground Color of the Cell</param>
		/// <param name="backColor">The background Color of the Cell</param>
		/// <param name="font">The Font used to draw the text in the Cell</param>
		public Cell(string text, object value, Color foreColor, Color backColor, Font font)
		{
			this.Init();

			this.text = text;
			this.data = value;
			this.ForeColor = foreColor;
			this.BackColor = backColor;
			this.Font = font;
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text, 
		/// object and CellStyle
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="value">The object displayed in the Cell</param>
		/// <param name="cellStyle">A CellStyle that specifies the visual appearance 
		/// of the Cell</param>
		public Cell(string text, object value, CellStyle cellStyle)
		{
			this.Init();

			this.text = text;
			this.data = value;
			this.cellStyle = cellStyle;
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text, 
		/// check value, fore Color, back Color and Font
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="check">Specifies whether the Cell is Checked</param>
		/// <param name="foreColor">The foreground Color of the Cell</param>
		/// <param name="backColor">The background Color of the Cell</param>
		/// <param name="font">The Font used to draw the text in the Cell</param>
		public Cell(string text, bool check, Color foreColor, Color backColor, Font font)
		{
			this.Init();

			this.text = text;
			this.Checked = check;
			this.ForeColor = foreColor;
			this.BackColor = backColor;
			this.Font = font;
		}


		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text, 
		/// check value and CellStyle
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="check">Specifies whether the Cell is Checked</param>
		/// <param name="cellStyle">A CellStyle that specifies the visual appearance 
		/// of the Cell</param>
		public Cell(string text, bool check, CellStyle cellStyle)
		{
			this.Init();

			this.text = text;
			this.Checked = check;
			this.cellStyle = cellStyle;
		}
		
		
		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text, 
		/// Image, fore Color, back Color and Font
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="image">The Image displayed in the Cell</param>
		/// <param name="foreColor">The foreground Color of the Cell</param>
		/// <param name="backColor">The background Color of the Cell</param>
		/// <param name="font">The Font used to draw the text in the Cell</param>
		public Cell(string text, Image image, Color foreColor, Color backColor, Font font)
		{
			this.Init();

			this.text = text;
			this.Image = image;
			this.ForeColor = foreColor;
			this.BackColor = backColor;
			this.Font = font;
		}
		
		
		/// <summary>
		/// Initializes a new instance of the Cell class with the specified text, 
		/// Image and CellStyle
		/// </summary>
		/// <param name="text">The text displayed in the Cell</param>
		/// <param name="image">The Image displayed in the Cell</param>
		/// <param name="cellStyle">A CellStyle that specifies the visual appearance 
		/// of the Cell</param>
		public Cell(string text, Image image, CellStyle cellStyle)
		{
			this.Init();

			this.text = text;
			this.Image = image;
			this.cellStyle = cellStyle;
		}


		/// <summary>
		/// Initialise default values
		/// </summary>
		private void Init()
		{
			this.text = null;
			this.data = null;
			this.rendererData = null;
			this.tag = null;
			this.row = null;
			this.index = -1;
			this.cellStyle = null;
			this.checkStyle = null;
			this.imageStyle = null;
			this.tooltipText = null;

			this.state = (byte) (STATE_EDITABLE | STATE_ENABLED);
		}

		#endregion


		#region Methods

		/// <summary>
		/// Releases all resources used by the Cell
		/// </summary>
		public void Dispose()
		{
			if (!this.disposed)
			{
				this.text = null;
				this.data = null;
				this.tag = null;
				this.rendererData = null;

				if (this.row != null)
				{
					this.row.Cells.Remove(this);
				}

				this.row = null;
				this.index = -1;
				this.cellStyle = null;
				this.checkStyle = null;
				this.imageStyle = null;
				this.tooltipText = null;

				this.state = (byte) 0;
				
				this.disposed = true;
			}
		}


		/// <summary>
		/// Returns the state represented by the specified state flag
		/// </summary>
		/// <param name="flag">A flag that represents the state to return</param>
		/// <returns>The state represented by the specified state flag</returns>
		internal bool GetState(int flag)
		{
			return ((this.state & flag) != 0);
		}


		/// <summary>
		/// Sets the state represented by the specified state flag to the specified value
		/// </summary>
		/// <param name="flag">A flag that represents the state to be set</param>
		/// <param name="value">The new value of the state</param>
		internal void SetState(int flag, bool value)
		{
			this.state = (byte) (value ? (this.state | flag) : (this.state & ~flag));
		}

		#endregion


		#region Properties

		/// <summary>
		/// Gets or sets the text displayed by the Cell
		/// </summary>
		[Category("Appearance"),
		DefaultValue(null),
		Description("The text displayed by the cell")]
		public string Text
		{
			get
			{
				return this.text;
			}

			set
			{
				if (this.text == null || !this.text.Equals(value))
				{
					string oldText = this.Text;
					
					this.text = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.ValueChanged, oldText));
				}
			}
		}


		/// <summary>
		/// Gets or sets the Cells non-text data
		/// </summary>
		[Category("Appearance"),
		DefaultValue(null),
		Description("The non-text data displayed by the cell"),
		TypeConverter(typeof(StringConverter))]
		public object Data
		{
			get
			{
				return this.data;
			}

			set
			{
				if (this.data != value)
				{
					object oldData = this.Data;
					
					this.data = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.ValueChanged, oldData));
				}
			}
		}


		/// <summary>
		/// Gets or sets the object that contains data about the Cell
		/// </summary>
		[Category("Appearance"),
		DefaultValue(null),
		Description("User defined data associated with the cell"),
		TypeConverter(typeof(StringConverter))]
		public object Tag
		{
			get
			{
				return this.tag;
			}

			set
			{
				this.tag = value;
			}
		}


		/// <summary>
		/// Gets or sets the CellStyle used by the Cell
		/// </summary>
		[Browsable(false),
		DefaultValue(null)]
		public CellStyle CellStyle
		{
			get
			{
				return this.cellStyle;
			}

			set
			{
				if (this.cellStyle != value)
				{
					CellStyle oldStyle = this.CellStyle;
					
					this.cellStyle = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.StyleChanged, oldStyle));
				}
			}
		}


		/// <summary>
		/// Gets or sets whether the Cell is selected
		/// </summary>
		[Browsable(false)]
		public bool Selected
		{
			get
			{
				return this.GetState(STATE_SELECTED);
			}
		}


		/// <summary>
		/// Sets whether the Cell is selected
		/// </summary>
		/// <param name="selected">A boolean value that specifies whether the 
		/// cell is selected</param>
		internal void SetSelected(bool selected)
		{
			this.SetState(STATE_SELECTED, selected);
		}


		/// <summary>
		/// Gets or sets the background Color for the Cell
		/// </summary>
		[Category("Appearance"),
		Description("The background color used to display text and graphics in the cell")]
		public Color BackColor
		{
			get
			{
				if (this.CellStyle == null)
				{
					if (this.Row != null)
					{
						return this.Row.BackColor;
					}

					return Color.Transparent;
				}
				
				return this.CellStyle.BackColor;
			}

			set
			{
				if (this.CellStyle == null)
				{
					this.CellStyle = new CellStyle();
				}
				
				if (this.CellStyle.BackColor != value)
				{
					Color oldBackColor = this.BackColor;
					
					this.CellStyle.BackColor = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.BackColorChanged, oldBackColor));
				}
			}
		}


		/// <summary>
		/// Specifies whether the BackColor property should be serialized at 
		/// design time
		/// </summary>
		/// <returns>true if the BackColor property should be serialized, 
		/// false otherwise</returns>
		private bool ShouldSerializeBackColor()
		{
			return (this.cellStyle != null && this.cellStyle.BackColor != Color.Empty);
		}


		/// <summary>
		/// Gets or sets the foreground Color for the Cell
		/// </summary>
		[Category("Appearance"),
		Description("The foreground color used to display text and graphics in the cell")]
		public Color ForeColor
		{
			get
			{
				if (this.CellStyle == null)
				{
					if (this.Row != null)
					{
						return this.Row.ForeColor;
					}

					return Color.Transparent;
				}
				else
				{
					if (this.CellStyle.ForeColor == Color.Empty || this.CellStyle.ForeColor == Color.Transparent)
					{
						if (this.Row != null)
						{
							return this.Row.ForeColor;
						}
					}

					return this.CellStyle.ForeColor;
				}
			}

			set
			{
				if (this.CellStyle == null)
				{
					this.CellStyle = new CellStyle();
				}
				
				if (this.CellStyle.ForeColor != value)
				{
					Color oldForeColor = this.ForeColor;
					
					this.CellStyle.ForeColor = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.ForeColorChanged, oldForeColor));
				}
			}
		}


		/// <summary>
		/// Specifies whether the ForeColor property should be serialized at 
		/// design time
		/// </summary>
		/// <returns>true if the ForeColor property should be serialized, 
		/// false otherwise</returns>
		private bool ShouldSerializeForeColor()
		{
			return (this.cellStyle != null && this.cellStyle.ForeColor != Color.Empty);
		}


		/// <summary>
		/// Gets or sets the Font used by the Cell
		/// </summary>
		[Category("Appearance"),
		Description("The font used to display text in the cell")]
		public Font Font
		{
			get
			{
				if (this.CellStyle == null)
				{
					if (this.Row != null)
					{
						return this.Row.Font;
					}

					return null;
				}
				else
				{
					if (this.CellStyle.Font == null)
					{
						if (this.Row != null)
						{
							return this.Row.Font;
						}
					}

					return this.CellStyle.Font;
				}
			}

			set
			{
				if (this.CellStyle == null)
				{
					this.CellStyle = new CellStyle();
				}
				
				if (this.CellStyle.Font != value)
				{
					Font oldFont = this.Font;
					
					this.CellStyle.Font = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.FontChanged, oldFont));
				}
			}
		}


		/// <summary>
		/// Specifies whether the Font property should be serialized at 
		/// design time
		/// </summary>
		/// <returns>true if the Font property should be serialized, 
		/// false otherwise</returns>
		private bool ShouldSerializeFont()
		{
			return (this.cellStyle != null && this.cellStyle.Font != null);
		}


		/// <summary>
		/// Gets or sets the amount of space between the Cells Border and its contents
		/// </summary>
		[Category("Appearance"),
		Description("The amount of space between the cells border and its contents")]
		public CellPadding Padding
		{
			get
			{
				if (this.CellStyle == null)
				{
					return CellPadding.Empty;
				}
				
				return this.CellStyle.Padding;
			}

			set
			{
				if (this.CellStyle == null)
				{
					this.CellStyle = new CellStyle();
				}
				
				if (this.CellStyle.Padding != value)
				{
					CellPadding oldPadding = this.Padding;
					
					this.CellStyle.Padding = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.PaddingChanged, oldPadding));
				}
			}
		}


		/// <summary>
		/// Specifies whether the Padding property should be serialized at 
		/// design time
		/// </summary>
		/// <returns>true if the Padding property should be serialized, 
		/// false otherwise</returns>
		private bool ShouldSerializePadding()
		{
			return this.Padding != CellPadding.Empty;
		}


		/// <summary>
		/// Gets or sets whether the Cell is in the checked state
		/// </summary>
		[Category("Appearance"),
		DefaultValue(false),
		Description("Indicates whether the cell is checked or unchecked"),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
		RefreshProperties(RefreshProperties.Repaint)]
		public bool Checked
		{
			get
			{
				if (this.checkStyle == null)
				{
					return false;
				}
				
				return this.checkStyle.Checked;
			}

			set
			{
				if (this.checkStyle == null)
				{
					this.checkStyle = new CellCheckStyle();
				}
				
				if (this.checkStyle.Checked != value)
				{
					bool oldCheck = this.Checked;
					
					this.checkStyle.Checked = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.CheckStateChanged, oldCheck));
				}
			}
		}


		/// <summary>
		/// Gets or sets the state of the Cells check box
		/// </summary>
		[Category("Appearance"),
		DefaultValue(CheckState.Unchecked),
		Description("Indicates the state of the cells check box"),
		RefreshProperties(RefreshProperties.Repaint)]
		public CheckState CheckState
		{
			get
			{
				if (this.checkStyle == null)
				{
					return CheckState.Unchecked;
				}
				
				return this.checkStyle.CheckState;
			}

			set
			{
				if (!Enum.IsDefined(typeof(CheckState), value))
				{
					throw new InvalidEnumArgumentException("value", (int) value, typeof(CheckState));
				}
				
				if (this.checkStyle == null)
				{
					this.checkStyle = new CellCheckStyle();
				}
				
				if (this.checkStyle.CheckState != value)
				{
					CheckState oldCheckState = this.CheckState;
					
					this.checkStyle.CheckState = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.CheckStateChanged, oldCheckState));
				}
			}
		}


		/// <summary>
		/// Gets or sets a value indicating whether the Cells check box 
		/// will allow three check states rather than two
		/// </summary>
		[Category("Appearance"),
		DefaultValue(false),
		Description("Controls whether or not the user can select the indeterminate state of the cells check box"),
		RefreshProperties(RefreshProperties.Repaint)]
		public bool ThreeState
		{
			get
			{
				if (this.checkStyle == null)
				{
					return false;
				}
				
				return this.checkStyle.ThreeState;
			}

			set
			{
				if (this.checkStyle == null)
				{
					this.checkStyle = new CellCheckStyle();
				}
				
				if (this.checkStyle.ThreeState != value)
				{
					bool oldThreeState = this.ThreeState;
					
					this.checkStyle.ThreeState = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.ThreeStateChanged, oldThreeState));
				}
			}
		}


		/// <summary>
		/// Gets or sets the image that is displayed in the Cell
		/// </summary>
		[Category("Appearance"),
		DefaultValue(null),
		Description("The image that will be displayed in the cell")]
		public Image Image
		{
			get
			{
				if (this.imageStyle == null)
				{
					return null;
				}
				
				return this.imageStyle.Image;
			}

			set
			{
				if (this.imageStyle == null)
				{
					this.imageStyle = new CellImageStyle();
				}
				
				if (this.imageStyle.Image != value)
				{
					Image oldImage = this.Image;
					
					this.imageStyle.Image = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.ImageChanged, oldImage));
				}
			}
		}


		/// <summary>
		/// Gets or sets how the Cells image is sized within the Cell
		/// </summary>
		[Category("Appearance"),
		DefaultValue(ImageSizeMode.Normal),
		Description("Controls how the image is sized within the cell")]
		public ImageSizeMode ImageSizeMode
		{
			get
			{
				if (this.imageStyle == null)
				{
					return ImageSizeMode.Normal;
				}
				
				return this.imageStyle.ImageSizeMode;
			}

			set
			{
				if (this.imageStyle == null)
				{
					this.imageStyle = new CellImageStyle();
				}
				
				if (this.imageStyle.ImageSizeMode != value)
				{
					ImageSizeMode oldSizeMode = this.ImageSizeMode;
					
					this.imageStyle.ImageSizeMode = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.ImageSizeModeChanged, oldSizeMode));
				}
			}
		}


		/// <summary>
		/// Gets or sets a value indicating whether the Cells contents are able 
		/// to be edited
		/// </summary>
		[Category("Appearance"),
		Description("Controls whether the cells contents are able to be changed by the user")]
		public bool Editable
		{
			get
			{
				if (!this.GetState(STATE_EDITABLE))
				{
					return false;
				}

				if (this.Row == null)
				{
					return this.Enabled;
				}

				return this.Enabled && this.Row.Editable;
			}

			set
			{
				bool editable = this.Editable;
				
				this.SetState(STATE_EDITABLE, value);
				
				if (editable != value)
				{
					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.EditableChanged, editable));
				}
			}
		}


		/// <summary>
		/// Specifies whether the Editable property should be serialized at 
		/// design time
		/// </summary>
		/// <returns>true if the Editable property should be serialized, 
		/// false otherwise</returns>
		private bool ShouldSerializeEditable()
		{
			return !this.GetState(STATE_EDITABLE);
		}


		/// <summary>
		/// Gets or sets a value indicating whether the Cell 
		/// can respond to user interaction
		/// </summary>
		[Category("Appearance"),
		Description("Indicates whether the cell is enabled")]
		public bool Enabled
		{
			get
			{
				if (!this.GetState(STATE_ENABLED))
				{
					return false;
				}

				if (this.Row == null)
				{
					return true;
				}

				return this.Row.Enabled;
			}

			set
			{
				bool enabled = this.Enabled;
				
				this.SetState(STATE_ENABLED, value);
				
				if (enabled != value)
				{
					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.EnabledChanged, enabled));
				}
			}
		}


		/// <summary>
		/// Specifies whether the Enabled property should be serialized at 
		/// design time
		/// </summary>
		/// <returns>true if the Enabled property should be serialized, 
		/// false otherwise</returns>
		private bool ShouldSerializeEnabled()
		{
			return !this.GetState(STATE_ENABLED);
		}


		/// <summary>
		/// Gets or sets the text displayed in the Cells tooltip
		/// </summary>
		[Category("Appearance"),
		DefaultValue(null),
		Description("The text displayed in the cells tooltip")]
		public string ToolTipText
		{
			get
			{
				return this.tooltipText;
			}

			set
			{
				if (this.tooltipText != value)
				{
					string oldToolTip = this.tooltipText;
					
					this.tooltipText = value;

					this.OnPropertyChanged(new CellEventArgs(this, CellEventType.ToolTipTextChanged, oldToolTip));
				}
			}
		}


		/// <summary>
		/// Gets or sets the information used by CellRenderers to record the current 
		/// state of the Cell
		/// </summary>
		protected internal object RendererData
		{
			get
			{
				return this.rendererData;
			}

			set
			{
				this.rendererData = value;
			}
		}


		/// <summary>
		/// Gets the Row that the Cell belongs to
		/// </summary>
		[Browsable(false)]
		public Row Row
		{
			get
			{
				return this.row;
			}
		}


		/// <summary>
		/// Gets or sets the Row that the Cell belongs to
		/// </summary>
		internal Row InternalRow
		{
			get
			{
				return this.row;
			}

			set
			{
				this.row = value;
			}
		}


		/// <summary>
		/// Gets the index of the Cell within its Row
		/// </summary>
		[Browsable(false)]
		public int Index
		{
			get
			{
				return this.index;
			}
		}


		/// <summary>
		/// Gets or sets the index of the Cell within its Row
		/// </summary>
		internal int InternalIndex
		{
			get
			{
				return this.index;
			}

			set
			{
				this.index = value;
			}
		}


		/// <summary>
		/// Gets whether the Cell is able to raise events
		/// </summary>
		protected internal bool CanRaiseEvents
		{
			get
			{
				// check if the Row that the Cell belongs to is able to 
				// raise events (if it can't, the Cell shouldn't raise 
				// events either)
				if (this.Row != null)
				{
					return this.Row.CanRaiseEvents;
				}

				return true;
			}
		}

		#endregion


		#region Events

		/// <summary>
		/// Raises the PropertyChanged event
		/// </summary>
		/// <param name="e">A CellEventArgs that contains the event data</param>
		protected virtual void OnPropertyChanged(CellEventArgs e)
		{
			e.SetColumn(this.Index);

			if (this.Row != null)
			{
				e.SetRow(this.Row.Index);
			}
			
			if (this.CanRaiseEvents)
			{
				if (this.Row != null)
				{
					this.Row.OnCellPropertyChanged(e);
				}
				
				if (PropertyChanged != null)
				{
					PropertyChanged(this, e);
				}
			}
		}

		#endregion
	}
}

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


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

Comments and Discussions