/* * OLVListItem - A row in an ObjectListView * * Author: Phillip Piper * Date: 31-March-2011 5:53 pm * * Change log: * v2.8 * 2014-09-27 JPP - Remove faulty caching of CheckState * 2014-05-06 JPP - Added OLVListItem.Enabled flag * vOld * 2011-03-31 JPP - Split into its own file * * Copyright (C) 2011-2014 Phillip Piper * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * If you wish to use this code in a closed source application, please contact phillip_piper@bigfoot.com. */ using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Drawing; namespace BrightIdeasSoftware { /// /// OLVListItems are specialized ListViewItems that know which row object they came from, /// and the row index at which they are displayed, even when in group view mode. They /// also know the image they should draw against themselves /// public class OLVListItem : ListViewItem { #region Constructors /// /// Create a OLVListItem for the given row object /// public OLVListItem(object rowObject) { this.rowObject = rowObject; } /// /// Create a OLVListItem for the given row object, represented by the given string and image /// public OLVListItem(object rowObject, string text, Object image) : base(text, -1) { this.rowObject = rowObject; this.imageSelector = image; } #endregion #region Properties /// /// Gets the bounding rectangle of the item, including all subitems /// new public Rectangle Bounds { get { try { return base.Bounds; } catch (System.ArgumentException) { // If the item is part of a collapsed group, Bounds will throw an exception return Rectangle.Empty; } } } /// /// Gets or sets how many pixels will be left blank around each cell of this item /// /// This setting only takes effect when the control is owner drawn. public Rectangle? CellPadding { get { return this.cellPadding; } set { this.cellPadding = value; } } private Rectangle? cellPadding; /// /// Gets or sets how the cells of this item will be vertically aligned /// /// This setting only takes effect when the control is owner drawn. public StringAlignment? CellVerticalAlignment { get { return this.cellVerticalAlignment; } set { this.cellVerticalAlignment = value; } } private StringAlignment? cellVerticalAlignment; /// /// Gets or sets the checkedness of this item. /// /// /// Virtual lists don't handle checkboxes well, so we have to intercept attempts to change them /// through the items, and change them into something that will work. /// Unfortuneately, this won't work if this property is set through the base class, since /// the property is not declared as virtual. /// new public bool Checked { get { return base.Checked; } set { if (this.Checked != value) { if (value) ((ObjectListView)this.ListView).CheckObject(this.RowObject); else ((ObjectListView)this.ListView).UncheckObject(this.RowObject); } } } /// /// Enable tri-state checkbox. /// /// .NET's Checked property was not built to handle tri-state checkboxes, /// and will return True for both Checked and Indeterminate states. public CheckState CheckState { get { switch (this.StateImageIndex) { case 0: return System.Windows.Forms.CheckState.Unchecked; case 1: return System.Windows.Forms.CheckState.Checked; case 2: return System.Windows.Forms.CheckState.Indeterminate; default: return System.Windows.Forms.CheckState.Unchecked; } } set { switch (value) { case System.Windows.Forms.CheckState.Unchecked: this.StateImageIndex = 0; break; case System.Windows.Forms.CheckState.Checked: this.StateImageIndex = 1; break; case System.Windows.Forms.CheckState.Indeterminate: this.StateImageIndex = 2; break; } } } /// /// Gets if this item has any decorations set for it. /// public bool HasDecoration { get { return this.decorations != null && this.decorations.Count > 0; } } /// /// Gets or sets the decoration that will be drawn over this item /// /// Setting this replaces all other decorations public IDecoration Decoration { get { if (this.HasDecoration) return this.Decorations[0]; else return null; } set { this.Decorations.Clear(); if (value != null) this.Decorations.Add(value); } } /// /// Gets the collection of decorations that will be drawn over this item /// public IList Decorations { get { if (this.decorations == null) this.decorations = new List(); return this.decorations; } } private IList decorations; /// /// Gets whether or not this row can be selected and activated /// public bool Enabled { get { return this.enabled; } internal set { this.enabled = value; } } private bool enabled; /// /// Get or set the image that should be shown against this item /// /// This can be an Image, a string or an int. A string or an int will /// be used as an index into the small image list. public Object ImageSelector { get { return imageSelector; } set { imageSelector = value; if (value is Int32) this.ImageIndex = (Int32)value; else if (value is String) this.ImageKey = (String)value; else this.ImageIndex = -1; } } private Object imageSelector; /// /// Gets or sets the the model object that is source of the data for this list item. /// public object RowObject { get { return rowObject; } set { rowObject = value; } } private object rowObject; #endregion #region Accessing /// /// Return the sub item at the given index /// /// Index of the subitem to be returned /// An OLVListSubItem public virtual OLVListSubItem GetSubItem(int index) { if (index >= 0 && index < this.SubItems.Count) return (OLVListSubItem)this.SubItems[index]; return null; } /// /// Return bounds of the given subitem /// /// This correctly calculates the bounds even for column 0. public virtual Rectangle GetSubItemBounds(int subItemIndex) { if (subItemIndex == 0) { Rectangle r = this.Bounds; Point sides = NativeMethods.GetScrolledColumnSides(this.ListView, subItemIndex); r.X = sides.X + 1; r.Width = sides.Y - sides.X; return r; } OLVListSubItem subItem = this.GetSubItem(subItemIndex); return subItem == null ? new Rectangle() : subItem.Bounds; } #endregion } }