//
// System.Web.UI.WebControls.ListView
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007-2010 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if NET_3_5
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
namespace System.Web.UI.WebControls{
[DefaultEvent ("SelectedIndexChanged")]
[DefaultProperty ("SelectedValue")]
[SupportsEventValidation]
[ControlValueProperty ("SelectedValue")]
[ToolboxBitmap (typeof (System.Web.UI.WebControls.ListView), "ListView.ico")]
[ToolboxItemFilter ("System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", ToolboxItemFilterType.Require)]
[Designer ("System.Web.UI.Design.WebControls.ListViewDesigner, System.Web.Extensions.Design, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
public class ListView : DataBoundControl, INamingContainer, IPageableItemContainer
{
const int CSTATE_BASE_STATE = 0;
const int CSTATE_DATAKEYNAMES = 1;
const int CSTATE_DATAKEYSSTATE = 2;
const int CSTATE_GROUPITEMCOUNT = 3;
const int CSTATE_TOTALROWCOUNT = 4;
const int CSTATE_EDITINDEX = 5;
const int CSTATE_SELECTEDINDEX = 6;
const int CSTATE_SORTDIRECTION = 7;
const int CSTATE_SORTEXPRESSION = 8;
const int CSTATE_COUNT = 9;
delegate void GroupStart ();
ITemplate _emptyDataTemplate;
ITemplate _emptyItemTemplate;
ITemplate _insertItemTemplate;
ITemplate _groupSeparatorTemplate;
ITemplate _groupTemplate;
ITemplate _itemSeparatorTemplate;
ITemplate _itemTemplate;
ITemplate _selectedItemTemplate;
ITemplate _alternatingItemTemplate;
ITemplate _editItemTemplate;
ITemplate _layoutTemplate;
int _totalRowCount;
int _startRowIndex = -1;
int _maximumRows = -1;
int _selectedIndex;
int _editIndex;
int _groupItemCount;
List <ListViewDataItem> _items;
string [] _dataKeyNames;
DataKeyArray _dataKeys;
ArrayList _dataKeyArray;
SortDirection _sortDirection = SortDirection.Ascending;
string _sortExpression = String.Empty;
Control _layoutTemplatePlaceholder;
Control _nonGroupedItemsContainer;
Control _groupedItemsContainer;
int _nonGroupedItemsContainerFirstItemIndex = -1;
int _groupedItemsContainerPlaceholderIndex = -1;
int _nonGroupedItemsContainerItemCount;
int _groupedItemsContainerItemCount;
IOrderedDictionary _lastInsertValues;
IOrderedDictionary _currentEditOldValues;
IOrderedDictionary _currentEditNewValues;
IOrderedDictionary _currentDeletingItemKeys;
IOrderedDictionary _currentDeletingItemValues;
int _firstIdAfterLayoutTemplate = 0;
bool usingFakeData;
#region Events
// Event keys
static readonly object ItemCancellingEvent = new object ();
static readonly object ItemCommandEvent = new object ();
static readonly object ItemCreatedEvent = new object ();
static readonly object ItemDataBoundEvent = new object ();
static readonly object ItemDeletedEvent = new object ();
static readonly object ItemDeletingEvent = new object ();
static readonly object ItemEditingEvent = new object ();
static readonly object ItemInsertedEvent = new object ();
static readonly object ItemInsertingEvent = new object ();
static readonly object ItemUpdatedEvent = new object ();
static readonly object ItemUpdatingEvent = new object ();
static readonly object LayoutCreatedEvent = new object ();
static readonly object PagePropertiesChangedEvent = new object ();
static readonly object PagePropertiesChangingEvent = new object ();
static readonly object SelectedIndexChangedEvent = new object ();
static readonly object SelectedIndexChangingEvent = new object ();
static readonly object SortedEvent = new object ();
static readonly object SortingEvent = new object ();
static readonly object TotalRowCountAvailableEvent = new object ();
[Category ("Action")]
public event EventHandler <ListViewCancelEventArgs> ItemCanceling {
add { Events.AddHandler (ItemCancellingEvent, value); }
remove { Events.RemoveHandler (ItemCancellingEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewCommandEventArgs> ItemCommand {
add { Events.AddHandler (ItemCommandEvent, value); }
remove { Events.RemoveHandler (ItemCommandEvent, value); }
}
[Category ("Behavior")]
public event EventHandler <ListViewItemEventArgs> ItemCreated {
add { Events.AddHandler (ItemCreatedEvent, value); }
remove { Events.RemoveHandler (ItemCreatedEvent, value); }
}
[Category ("Data")]
public event EventHandler <ListViewItemEventArgs> ItemDataBound {
add { Events.AddHandler (ItemDataBoundEvent, value); }
remove { Events.RemoveHandler (ItemDataBoundEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewDeletedEventArgs> ItemDeleted {
add { Events.AddHandler (ItemDeletedEvent, value); }
remove { Events.RemoveHandler (ItemDeletedEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewDeleteEventArgs> ItemDeleting {
add { Events.AddHandler (ItemDeletingEvent, value); }
remove { Events.RemoveHandler (ItemDeletingEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewEditEventArgs> ItemEditing {
add { Events.AddHandler (ItemEditingEvent, value); }
remove { Events.RemoveHandler (ItemEditingEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewInsertedEventArgs> ItemInserted {
add { Events.AddHandler (ItemInsertedEvent, value); }
remove { Events.RemoveHandler (ItemInsertedEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewInsertEventArgs> ItemInserting {
add { Events.AddHandler (ItemInsertingEvent, value); }
remove { Events.RemoveHandler (ItemInsertingEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewUpdatedEventArgs> ItemUpdated {
add { Events.AddHandler (ItemUpdatedEvent, value); }
remove { Events.RemoveHandler (ItemUpdatedEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewUpdateEventArgs> ItemUpdating {
add { Events.AddHandler (ItemUpdatingEvent, value); }
remove { Events.RemoveHandler (ItemUpdatingEvent, value); }
}
[Category ("Behavior")]
public event EventHandler LayoutCreated {
add { Events.AddHandler (LayoutCreatedEvent, value); }
remove { Events.RemoveHandler (LayoutCreatedEvent, value); }
}
[Category ("Behavior")]
public event EventHandler PagePropertiesChanged {
add { Events.AddHandler (PagePropertiesChangedEvent, value); }
remove { Events.RemoveHandler (PagePropertiesChangedEvent, value); }
}
[Category ("Behavior")]
public event EventHandler <PagePropertiesChangingEventArgs> PagePropertiesChanging {
add { Events.AddHandler (PagePropertiesChangingEvent, value); }
remove { Events.RemoveHandler (PagePropertiesChangingEvent, value); }
}
[Category ("Action")]
public event EventHandler SelectedIndexChanged {
add { Events.AddHandler (SelectedIndexChangedEvent, value); }
remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewSelectEventArgs> SelectedIndexChanging {
add { Events.AddHandler (SelectedIndexChangingEvent, value); }
remove { Events.RemoveHandler (SelectedIndexChangingEvent, value); }
}
[Category ("Action")]
public event EventHandler Sorted {
add { Events.AddHandler (SortedEvent, value); }
remove { Events.RemoveHandler (SortedEvent, value); }
}
[Category ("Action")]
public event EventHandler <ListViewSortEventArgs> Sorting {
add { Events.AddHandler (SortingEvent, value); }
remove { Events.RemoveHandler (SortingEvent, value); }
}
event EventHandler <PageEventArgs> IPageableItemContainer.TotalRowCountAvailable {
add { Events.AddHandler (TotalRowCountAvailableEvent, value); }
remove { Events.RemoveHandler (TotalRowCountAvailableEvent, value); }
}
#endregion
#region Properties
IOrderedDictionary CurrentEditOldValues {
get {
if (_currentEditOldValues == null)
_currentEditOldValues = new OrderedDictionary ();
return _currentEditOldValues;
}
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[EditorBrowsable (EditorBrowsableState.Never)]
[Browsable (false)]
public override string AccessKey {
get { return base.AccessKey; }
set { throw StylingNotSupported (); }
}
[PersistenceMode (PersistenceMode.InnerProperty)]
[DefaultValue ("")]
[Browsable (false)]
[TemplateContainer (typeof (System.Web.UI.WebControls.ListViewDataItem), BindingDirection.TwoWay)]
public virtual ITemplate AlternatingItemTemplate {
get { return _alternatingItemTemplate; }
set { _alternatingItemTemplate = value; }
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[EditorBrowsable (EditorBrowsableState.Never)]
[Browsable (false)]
public override Color BackColor {
get { return base.BackColor; }
set { throw StylingNotSupported (); }
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
[EditorBrowsable (EditorBrowsableState.Never)]
public override Color BorderColor {
get { return base.BorderColor; }
set { throw StylingNotSupported (); }
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[EditorBrowsable (EditorBrowsableState.Never)]
[Browsable (false)]
public override BorderStyle BorderStyle {
get { return base.BorderStyle; }
set { throw StylingNotSupported (); }
}
[Browsable (false)]
[EditorBrowsable (EditorBrowsableState.Never)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public override Unit BorderWidth {
get { return base.BorderWidth; }
set { throw StylingNotSupported (); }
}
public override ControlCollection Controls {
get {
EnsureChildControls ();
return base.Controls;
}
}
[Category ("Behavior")]
[DefaultValue (true)]
public virtual bool ConvertEmptyStringToNull {
get {
object o = ViewState ["ConvertEmptyStringToNull"];
if (o != null)
return (bool) o;
return true;
}
set { ViewState ["ConvertEmptyStringToNull"] = value; }
}
[EditorBrowsable (EditorBrowsableState.Never)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
[CssClassProperty]
public override string CssClass {
get { return base.CssClass; }
set { throw StylingNotSupported (); }
}
[Editor ("System.Web.UI.Design.WebControls.DataFieldEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof (System.Drawing.Design.UITypeEditor))]
[DefaultValue ("")]
[TypeConverter (typeof (System.Web.UI.WebControls.StringArrayConverter))]
[Category ("Data")]
public virtual string [] DataKeyNames {
get {
if (_dataKeyNames != null)
return _dataKeyNames;
return new string [0];
}
set {
if (value == null)
_dataKeyNames = null;
else
_dataKeyNames = (string []) value.Clone ();
// They will eventually be recreated while creating the child controls
_dataKeyArray = null;
_dataKeys = null;
if (Initialized)
RequiresDataBinding = true;
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public virtual DataKeyArray DataKeys {
get {
if (_dataKeys == null) {
_dataKeys = new DataKeyArray (DataKeyArray);
if (IsTrackingViewState)
((IStateManager) _dataKeys).TrackViewState ();
}
return _dataKeys;
}
}
ArrayList DataKeyArray {
get {
if (_dataKeyArray == null)
_dataKeyArray = new ArrayList ();
return _dataKeyArray;
}
}
[DefaultValue (-1)]
[Category ("Default")]
public virtual int EditIndex {
get { return _editIndex; }
set {
if (value < -1)
throw new ArgumentOutOfRangeException ("value");
if (value != _editIndex) {
_editIndex = value;
if (Initialized)
RequiresDataBinding = true;
}
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public virtual ListViewItem EditItem {
get {
IList <ListViewDataItem> items = Items;
if (_editIndex >= 0 && _editIndex < items.Count)
return items [_editIndex];
return null;
}
}
[TemplateContainer (typeof (System.Web.UI.WebControls.ListViewDataItem), BindingDirection.TwoWay)]
[PersistenceMode (PersistenceMode.InnerProperty)]
[Browsable (false)]
[DefaultValue ("")]
public virtual ITemplate EditItemTemplate {
get { return _editItemTemplate; }
set { _editItemTemplate = value; }
}
[TemplateContainer (typeof (System.Web.UI.WebControls.ListView))]
[PersistenceMode (PersistenceMode.InnerProperty)]
[DefaultValue ("")]
[Browsable (false)]
public virtual ITemplate EmptyDataTemplate {
get { return _emptyDataTemplate; }
set { _emptyDataTemplate = value; }
}
[Browsable (false)]
[TemplateContainer (typeof (System.Web.UI.WebControls.ListViewItem))]
[DefaultValue ("")]
[PersistenceMode (PersistenceMode.InnerProperty)]
public virtual ITemplate EmptyItemTemplate {
get { return _emptyItemTemplate; }
set { _emptyItemTemplate = value; }
}
[WebCategory ("Behavior")]
[DefaultValue (false)]
[MonoTODO ("Figure out where it is used and what's the effect of setting it to true.")]
public virtual bool EnableModelValidation {
get {
object o = ViewState ["EnableModelValidation"];
if (o == null)
return false;
return (bool)o;
}
set {
if (value)
ViewState ["EnableModelValidation"] = value;
}
}
[Browsable (false)]
[EditorBrowsable (EditorBrowsableState.Never)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public override FontInfo Font {
get { throw StylingNotSupported (); }
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[EditorBrowsable (EditorBrowsableState.Never)]
[Browsable (false)]
public override Color ForeColor {
get { return base.ForeColor; }
set { throw StylingNotSupported (); }
}
[Category ("Default")]
[DefaultValue (1)]
public virtual int GroupItemCount {
get { return _groupItemCount; }
set {
if (value < 1)
throw new ArgumentOutOfRangeException ("value");
if (value != _groupItemCount) {
_groupItemCount = value;
if (Initialized)
RequiresDataBinding = true;
}
}
}
[Category ("Behavior")]
[DefaultValue ("groupPlaceholder")]
public virtual string GroupPlaceholderID {
get {
string s = ViewState ["GroupPlaceholderID"] as string;
if (s != null)
return s;
return "groupPlaceholder";
}
set {
if (String.IsNullOrEmpty (value))
throw new ArgumentOutOfRangeException ("value");
ViewState ["GroupPlaceholderID"] = value;
}
}
[TemplateContainer (typeof (System.Web.UI.WebControls.ListViewItem))]
[PersistenceMode (PersistenceMode.InnerProperty)]
[Browsable (false)]
[DefaultValue ("")]
public virtual ITemplate GroupSeparatorTemplate {
get { return _groupSeparatorTemplate; }
set { _groupSeparatorTemplate = value; }
}
[TemplateContainer (typeof (System.Web.UI.WebControls.ListViewItem))]
[PersistenceMode (PersistenceMode.InnerProperty)]
[DefaultValue ("")]
[Browsable (false)]
public virtual ITemplate GroupTemplate {
get { return _groupTemplate; }
set { _groupTemplate = value; }
}
[EditorBrowsable (EditorBrowsableState.Never)]
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public override Unit Height {
get { return base.Height; }
set { throw StylingNotSupported (); }
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
public virtual ListViewItem InsertItem {
get;
private set;
}
[Category ("Default")]
[DefaultValue (InsertItemPosition.None)]
public virtual InsertItemPosition InsertItemPosition {
get;
set;
}
[TemplateContainer (typeof (System.Web.UI.WebControls.ListViewItem), BindingDirection.TwoWay)]
[PersistenceMode (PersistenceMode.InnerProperty)]
[DefaultValue ("")]
[Browsable (false)]
public virtual ITemplate InsertItemTemplate {
get { return _insertItemTemplate; }
set { _insertItemTemplate = value; }
}
[DefaultValue ("itemPlaceholder")]
[Category ("Behavior")]
public virtual string ItemPlaceholderID {
get {
string s = ViewState ["ItemPlaceHolderID"] as string;
if (s != null)
return s;
return "itemPlaceholder";
}
set {
if (String.IsNullOrEmpty (value))
throw new ArgumentOutOfRangeException ("value");
ViewState ["ItemPlaceHolderID"] = value;
}
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
public virtual IList <ListViewDataItem> Items {
get {
if (_items == null)
_items = new List <ListViewDataItem> ();
return _items;
}
}
[PersistenceMode (PersistenceMode.InnerProperty)]
[DefaultValue ("")]
[Browsable (false)]
[TemplateContainer (typeof (System.Web.UI.WebControls.ListViewItem))]
public virtual ITemplate ItemSeparatorTemplate {
get { return _itemSeparatorTemplate; }
set { _itemSeparatorTemplate = value; }
}
[Browsable (false)]
[PersistenceMode (PersistenceMode.InnerProperty)]
[TemplateContainer (typeof (System.Web.UI.WebControls.ListViewDataItem), BindingDirection.TwoWay)]
[DefaultValue ("")]
public virtual ITemplate ItemTemplate {
get { return _itemTemplate; }
set { _itemTemplate = value; }
}
[TemplateContainer (typeof (System.Web.UI.WebControls.ListView))]
[PersistenceMode (PersistenceMode.InnerProperty)]
[DefaultValue ("")]
[Browsable (false)]
public virtual ITemplate LayoutTemplate {
get { return _layoutTemplate; }
set { _layoutTemplate = value; }
}
protected virtual int MaximumRows {
get { return _maximumRows; }
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public virtual DataKey SelectedDataKey {
get {
if (_dataKeyNames == null || _dataKeyNames.Length == 0)
throw new InvalidOperationException ("Data keys must be specified on ListView '" + ID + "' before the selected data keys can be retrieved. Use the DataKeyNames property to specify data keys.");
DataKeyArray dataKeys = DataKeys;
int selIndex = SelectedIndex;
if (selIndex > -1 && selIndex < dataKeys.Count)
return dataKeys [selIndex];
return null;
}
}
[Browsable (false)]
public virtual DataKey SelectedPersistedDataKey {
get;
set;
}
[Category ("Default")]
[DefaultValue (-1)]
public virtual int SelectedIndex {
get { return _selectedIndex; }
set {
if (value < -1)
throw new ArgumentOutOfRangeException ("value");
if (value != _selectedIndex) {
_selectedIndex = value;
if (Initialized)
RequiresDataBinding = true;
}
}
}
[PersistenceMode (PersistenceMode.InnerProperty)]
[DefaultValue ("")]
[Browsable (false)]
[TemplateContainer (typeof (System.Web.UI.WebControls.ListViewDataItem), BindingDirection.TwoWay)]
public virtual ITemplate SelectedItemTemplate {
get { return _selectedItemTemplate; }
set { _selectedItemTemplate = value; }
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
public object SelectedValue {
get {
DataKey dk = SelectedDataKey;
if (dk != null)
return dk.Value;
return null;
}
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
[DefaultValue (SortDirection.Ascending)]
[PersistenceMode (PersistenceMode.InnerProperty)]
public virtual SortDirection SortDirection {
get { return _sortDirection; }
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public virtual string SortExpression {
get { return _sortExpression; }
}
protected virtual int StartRowIndex {
get {
if (_startRowIndex < 0)
return 0;
return _startRowIndex;
}
}
int IPageableItemContainer.MaximumRows {
get { return MaximumRows; }
}
int IPageableItemContainer.StartRowIndex {
get { return StartRowIndex; }
}
[EditorBrowsable (EditorBrowsableState.Never)]
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public override short TabIndex {
get { return 0; }
set { throw new NotSupportedException ("ListView does not allow setting this property."); }
}
[EditorBrowsable (EditorBrowsableState.Never)]
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public override string ToolTip {
get { return base.ToolTip; }
set { throw StylingNotSupported (); }
}
[EditorBrowsable (EditorBrowsableState.Never)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
public override Unit Width {
get { return base.Width; }
set { throw StylingNotSupported (); }
}
#endregion
public ListView ()
{
InsertItemPosition = InsertItemPosition.None;
ResetDefaults ();
}
void ResetDefaults ()
{
_totalRowCount = -1;
_selectedIndex = -1;
_editIndex = -1;
_groupItemCount = 1;
}
protected virtual void AddControlToContainer (Control control, Control container, int addLocation)
{
if (control == null)
throw new ArgumentNullException ("control");
// .NET doesn't check container for null (!)
// if (container == null)
// throw new ArgumentNullException ("container");
Control ctl;
if (container is HtmlTable) {
ctl = new ListViewTableRow ();
ctl.Controls.Add (control);
} else if (container is HtmlTableRow) {
ctl = new ListViewTableCell ();
ctl.Controls.Add (control);
} else
ctl = control;
container.Controls.AddAt (addLocation, ctl);
}
protected internal override void CreateChildControls ()
{
object itemCount = ViewState ["_!ItemCount"];
if (itemCount != null) {
int c = (int)itemCount;
if (c >= 0) {
// Fake data - we only need to make sure
// OnTotalRowCountAvailable is called now - so that any
// pagers can create child controls.
object[] data = new object [c];
usingFakeData = true;
try {
CreateChildControls (data, false);
} finally {
usingFakeData = false;
}
}
} else if (RequiresDataBinding)
EnsureDataBound ();
base.CreateChildControls ();
}
protected virtual int CreateChildControls (IEnumerable dataSource, bool dataBinding)
{
IList <ListViewDataItem> retList = null;
EnsureLayoutTemplate ();
RemoveItems ();
// If any of the _maximumRows or _startRowIndex is different to their
// defaults, it means we are paging - i.e. SetPageProperties has been
// called.
bool haveDataToPage = _maximumRows > 0 || _startRowIndex > 0;
var pagedDataSource = new ListViewPagedDataSource ();
if (dataBinding) {
DataSourceView view = GetData ();
if (view == null)
throw new InvalidOperationException ("dataSource returned a null reference for DataSourceView.");
int totalRowCount = 0;
if (haveDataToPage && view.CanPage) {
pagedDataSource.AllowServerPaging = true;
if (view.CanRetrieveTotalRowCount)
totalRowCount = SelectArguments.TotalRowCount;
else {
ICollection ds = dataSource as ICollection;
if (ds == null)
throw new InvalidOperationException ("dataSource does not implement the ICollection interface.");
totalRowCount = ds.Count + StartRowIndex;
}
}
pagedDataSource.TotalRowCount = totalRowCount;
_totalRowCount = totalRowCount;
DataKeyArray.Clear ();
} else {
if (!(dataSource is ICollection))
throw new InvalidOperationException ("dataSource does not implement the ICollection interface and dataBinding is false.");
pagedDataSource.TotalRowCount = _totalRowCount;
_totalRowCount = -1;
}
pagedDataSource.StartRowIndex = StartRowIndex;
pagedDataSource.MaximumRows = MaximumRows;
pagedDataSource.DataSource = dataSource;
bool emptySet = false;
if (dataSource != null) {
if (GroupItemCount <= 1 && GroupTemplate == null)
retList = CreateItemsWithoutGroups (pagedDataSource, dataBinding, InsertItemPosition, DataKeyArray);
else
retList = CreateItemsInGroups (pagedDataSource, dataBinding, InsertItemPosition, DataKeyArray);
if (retList == null || retList.Count == 0)
emptySet = true;
if (haveDataToPage) {
// Data source has paged data for us, so we must use its total row
// count
_totalRowCount = pagedDataSource.DataSourceCount;
} else if (!emptySet && _totalRowCount > -1)
_totalRowCount = retList.Count;
else if (_totalRowCount > -1)
_totalRowCount = 0;
OnTotalRowCountAvailable (new PageEventArgs (_startRowIndex, _maximumRows, _totalRowCount));
} else
emptySet = true;
if (!usingFakeData && emptySet) {
Controls.Clear ();
CreateEmptyDataItem ();
}
if (retList == null)
return 0;
return _totalRowCount;
}
protected override Style CreateControlStyle ()
{
throw StylingNotSupported ();
}
protected virtual ListViewDataItem CreateDataItem (int dataItemIndex, int displayIndex)
{
return new ListViewDataItem (dataItemIndex, displayIndex);
}
protected override DataSourceSelectArguments CreateDataSourceSelectArguments ()
{
DataSourceSelectArguments arg = DataSourceSelectArguments.Empty;
DataSourceView view = GetData();
if (view.CanPage) {
arg.StartRowIndex = _startRowIndex;
if (view.CanRetrieveTotalRowCount) {
arg.RetrieveTotalRowCount = true;
arg.MaximumRows = _maximumRows;
} else
arg.MaximumRows = -1;
}
if (IsBoundUsingDataSourceID && !String.IsNullOrEmpty (_sortExpression)) {
if (_sortDirection == SortDirection.Ascending)
arg.SortExpression = _sortExpression;
else
arg.SortExpression = _sortExpression + " DESC";
}
return arg;
}
protected virtual void CreateEmptyDataItem ()
{
if (_emptyDataTemplate != null) {
ListViewItem item = CreateItem (ListViewItemType.EmptyItem);
InstantiateEmptyDataTemplate (item);
OnItemCreated (new ListViewItemEventArgs (item));
AddControlToContainer (item, this, 0);
}
}
protected virtual ListViewItem CreateEmptyItem ()
{
if (_emptyItemTemplate != null) {
ListViewItem item = CreateItem (ListViewItemType.EmptyItem);
InstantiateEmptyItemTemplate (item);
OnItemCreated (new ListViewItemEventArgs (item));
return item;
}
return null;
}
protected virtual ListViewItem CreateInsertItem ()
{
if (_insertItemTemplate == null)
// .NET throws a different message, but it's incorrect so we'll use
// this one
throw new InvalidOperationException ("The ListView control '" + ID + "' does not have an InsertItemTemplate template specified.");
ListViewItem ret = CreateItem (ListViewItemType.InsertItem);
InstantiateInsertItemTemplate (ret);
OnItemCreated (new ListViewItemEventArgs (ret));
InsertItem = ret;
return ret;
}
protected virtual ListViewItem CreateItem (ListViewItemType itemType)
{
return new ListViewItem (itemType);
}
void InsertSeparatorItem (Control container, int position)
{
Control control = CreateItem (ListViewItemType.DataItem);
InstantiateItemSeparatorTemplate (control);
AddControlToContainer (control, container, position);
}
ListViewDataItem InsertDataItem (object dataItem, Control container, bool dataBinding, ArrayList keyArray, int startIndex, int position, ref int displayIndex)
{
ListViewDataItem lvdi = CreateDataItem (startIndex + displayIndex, displayIndex);
InstantiateItemTemplate (lvdi, displayIndex);
if (dataBinding) {
lvdi.DataItem = dataItem;
OrderedDictionary dict = new OrderedDictionary ();
string[] dataKeyNames = DataKeyNames;
foreach (string s in dataKeyNames)
dict.Add (s, DataBinder.GetPropertyValue (dataItem, s));
DataKey dk = new DataKey (dict, dataKeyNames);
if (keyArray.Count == displayIndex)
keyArray.Add (dk);
else
keyArray [displayIndex] = dk;
}
OnItemCreated (new ListViewItemEventArgs (lvdi));
AddControlToContainer (lvdi, container, position);
if (dataBinding) {
lvdi.DataBind ();
OnItemDataBound (new ListViewItemEventArgs (lvdi));
}
displayIndex++;
return lvdi;
}
protected virtual IList <ListViewDataItem> CreateItemsInGroups (ListViewPagedDataSource dataSource, bool dataBinding, InsertItemPosition insertPosition,
ArrayList keyArray)
{
if (_groupTemplate == null)
return null;
if (_groupedItemsContainer == null)
_groupedItemsContainer = FindPlaceholder (GroupPlaceholderID, this);
if (_groupedItemsContainer == null)
throw NoPlaceholder (true);
Control parent = _groupedItemsContainer.Parent;
int gpos;
if (_groupedItemsContainerPlaceholderIndex == -1) {
gpos = 0;
if (parent != null) {
gpos = parent.Controls.IndexOf (_groupedItemsContainer);
parent.Controls.Remove (_groupedItemsContainer);
_groupedItemsContainer = parent;
if (_groupedItemsContainer != _layoutTemplatePlaceholder)
AddControlToContainer (_groupedItemsContainer, _layoutTemplatePlaceholder, 0);
}
_groupedItemsContainerPlaceholderIndex = gpos;
} else {
gpos = _groupedItemsContainerPlaceholderIndex;
ResetChildNames (_firstIdAfterLayoutTemplate);
}
IList <ListViewDataItem> ret = Items;
ret.Clear ();
int firstItemIndexInGroup = -1;
Control currentGroup = StartNewGroup (false, ref gpos, ref firstItemIndexInGroup);
int groupItemCount = GroupItemCount;
int itemPosInGroup = firstItemIndexInGroup;
int groupItemCounter = groupItemCount;
ListViewItem lvi;
ListViewItem container;
bool needSeparator = false;
bool haveSeparatorTemplate = _itemSeparatorTemplate != null;
if (insertPosition == InsertItemPosition.FirstItem) {
lvi = CreateInsertItem ();
AddControlToContainer (lvi, currentGroup, itemPosInGroup++);
groupItemCounter--;
needSeparator = true;
}
int displayIndex = 0;
ListViewDataItem lvdi;
int startIndex = dataSource.StartRowIndex;
int dataCount = dataSource.Count;
int numberOfGroups = (dataCount / groupItemCount) + (dataCount % groupItemCount) - 1;
GroupStart groupStart = () => {
if (groupItemCounter <= 0) {
groupItemCounter = groupItemCount;
currentGroup = StartNewGroup (numberOfGroups >= 1, ref gpos, ref firstItemIndexInGroup);
numberOfGroups--;
itemPosInGroup = firstItemIndexInGroup;
_groupedItemsContainerItemCount++;
needSeparator = false;
}
};
foreach (object item in dataSource) {
groupStart ();
if (needSeparator && haveSeparatorTemplate)
InsertSeparatorItem (currentGroup, itemPosInGroup++);
ret.Add (InsertDataItem (item, currentGroup, dataBinding, keyArray, startIndex, itemPosInGroup++, ref displayIndex));
groupItemCounter--;
if (!needSeparator)
needSeparator = true;
}
groupStart ();
if (insertPosition == InsertItemPosition.LastItem) {
if (needSeparator && haveSeparatorTemplate)
InsertSeparatorItem (currentGroup, itemPosInGroup++);
groupStart ();
lvi = CreateInsertItem ();
AddControlToContainer (lvi, currentGroup, itemPosInGroup++);
groupItemCounter--;
}
if (groupItemCounter > 0 && _emptyItemTemplate != null) {
while (groupItemCounter > 0) {
if (haveSeparatorTemplate)
InsertSeparatorItem (currentGroup, itemPosInGroup++);
lvi = CreateEmptyItem ();
AddControlToContainer (lvi, currentGroup, itemPosInGroup++);
groupItemCounter--;
}
}
return ret;
}
Control StartNewGroup (bool needSeparator, ref int position, ref int firstItemIndexInGroup)
{
Control control = new ListViewContainer ();
InstantiateGroupTemplate (control);
Control placeholder = FindPlaceholder (ItemPlaceholderID, control);
if (placeholder == null)
throw NoPlaceholder (false);
Control parent = placeholder.Parent;
firstItemIndexInGroup = parent.Controls.IndexOf (placeholder);
if (needSeparator) {
Control separator = new Control ();
InstantiateGroupSeparatorTemplate (separator);
if (separator.Controls.Count > 0) {
AddControlToContainer (separator, _groupedItemsContainer, position++);
_groupedItemsContainerItemCount++;
} else
separator = null;
}
parent.Controls.RemoveAt (firstItemIndexInGroup);
AddControlToContainer (control, _groupedItemsContainer, position++);
return parent;
}
protected virtual IList <ListViewDataItem> CreateItemsWithoutGroups (ListViewPagedDataSource dataSource, bool dataBinding, InsertItemPosition insertPosition,
ArrayList keyArray)
{
if (_nonGroupedItemsContainer == null)
_nonGroupedItemsContainer = FindPlaceholder (ItemPlaceholderID, this);
_nonGroupedItemsContainerItemCount = 0;
if (_nonGroupedItemsContainer == null)
throw NoPlaceholder (false);
Control parent = _nonGroupedItemsContainer.Parent;
int ipos;
if (_nonGroupedItemsContainerFirstItemIndex == -1) {
ipos = 0;
if (parent != null) {
ipos = parent.Controls.IndexOf (_nonGroupedItemsContainer);
parent.Controls.Remove (_nonGroupedItemsContainer);
_nonGroupedItemsContainer = parent;
if (_nonGroupedItemsContainer != _layoutTemplatePlaceholder)
AddControlToContainer (_nonGroupedItemsContainer, _layoutTemplatePlaceholder, 0);
}
_nonGroupedItemsContainerFirstItemIndex = ipos;
} else {
ipos = _nonGroupedItemsContainerFirstItemIndex;
ResetChildNames (_firstIdAfterLayoutTemplate);
}
IList <ListViewDataItem> ret = Items;
ret.Clear ();
ListViewItem lvi;
ListViewItem container;
bool needSeparator = false;
if (insertPosition == InsertItemPosition.FirstItem) {
lvi = CreateInsertItem ();
AddControlToContainer (lvi, _nonGroupedItemsContainer, ipos++);
_nonGroupedItemsContainerItemCount++;
needSeparator = true;
}
bool haveSeparatorTemplate = _itemSeparatorTemplate != null;
int displayIndex = 0;
int startIndex = dataSource.StartRowIndex;
foreach (object item in dataSource) {
if (needSeparator && haveSeparatorTemplate) {
InsertSeparatorItem (_nonGroupedItemsContainer, ipos++);
_nonGroupedItemsContainerItemCount++;
}
ret.Add (InsertDataItem (item, _nonGroupedItemsContainer, dataBinding, keyArray, startIndex, ipos++, ref displayIndex));
_nonGroupedItemsContainerItemCount++;
if (!needSeparator)
needSeparator = true;
}
if (insertPosition == InsertItemPosition.LastItem) {
if (needSeparator && haveSeparatorTemplate) {
container = new ListViewItem ();
InstantiateItemSeparatorTemplate (container);
AddControlToContainer (container, _nonGroupedItemsContainer, ipos++);
_nonGroupedItemsContainerItemCount++;
}
lvi = CreateInsertItem ();
AddControlToContainer (lvi, _nonGroupedItemsContainer, ipos++);
_nonGroupedItemsContainerItemCount++;
}
return ret;
}
protected virtual void CreateLayoutTemplate ()
{
if (_layoutTemplate != null) {
_layoutTemplatePlaceholder = new Control ();
_layoutTemplate.InstantiateIn (_layoutTemplatePlaceholder);
Controls.Add (_layoutTemplatePlaceholder);
}
OnLayoutCreated (EventArgs.Empty);
}
public virtual void DeleteItem (int itemIndex)
{
if (itemIndex < 0)
throw new InvalidOperationException ("itemIndex is less than 0.");
IList <ListViewDataItem> items = Items;
if (itemIndex < items.Count)
DoDelete (items [itemIndex], itemIndex);
}
protected virtual void EnsureLayoutTemplate ()
{
if (Controls.Count != 0)
return;
CreateLayoutTemplate ();
_firstIdAfterLayoutTemplate = GetDefaultNumberID ();
}
public virtual void ExtractItemValues (IOrderedDictionary itemValues, ListViewItem item, bool includePrimaryKey)
{
if (itemValues == null)
throw new ArgumentNullException ("itemValues");
IBindableTemplate bt = null;
if (item.ItemType == ListViewItemType.DataItem) {
ListViewDataItem dataItem = item as ListViewDataItem;
if (dataItem == null)
throw new InvalidOperationException ("item is not a ListViewDataItem object.");
int displayIndex = dataItem.DisplayIndex;
if (_editItemTemplate != null && displayIndex == EditIndex)
bt = (IBindableTemplate) _editItemTemplate;
else if (_selectedItemTemplate != null && (displayIndex == SelectedIndex))
bt = (IBindableTemplate) _selectedItemTemplate;
else if (_alternatingItemTemplate != null && (displayIndex % 2 != 0))
bt = (IBindableTemplate) _alternatingItemTemplate;
else
bt = (IBindableTemplate) _itemTemplate;
} else if (_insertItemTemplate != null && item.ItemType == ListViewItemType.InsertItem)
bt = (IBindableTemplate) _insertItemTemplate;
if (bt == null)
return;
IOrderedDictionary values = bt.ExtractValues (item);
if (values == null || values.Count == 0)
return;
string[] keyNames = includePrimaryKey ? null : DataKeyNames;
bool haveKeyNames = keyNames != null && keyNames.Length > 0;
object key, value;
string s;
bool convertEmptyStringToNull = ConvertEmptyStringToNull;
foreach (DictionaryEntry de in values) {
key = de.Key;
if (includePrimaryKey || (haveKeyNames && Array.IndexOf (keyNames, key) != -1)) {
value = de.Value;
if (convertEmptyStringToNull) {
s = value as string;
if (s != null && s.Length == 0)
value = null;
}
itemValues [key] = value;
}
}
}
protected virtual Control FindPlaceholder (string containerID, Control container)
{
// .NET doesn't check whether container is null (!)
if (String.IsNullOrEmpty (containerID))
return null;
if (container.ID == containerID)
return container;
Control ret = container.FindControl (containerID);
if (ret != null)
return ret;
foreach (Control c in container.Controls) {
ret = FindPlaceholder (containerID, c);
if (ret != null)
return ret;
}
return null;
}
public virtual void InsertNewItem (bool causesValidation)
{
ListViewItem insertItem = InsertItem;
if (insertItem == null)
throw new InvalidOperationException ("The ListView control does not have an insert item.");
if (causesValidation) {
Page page = Page;
if (page != null)
page.Validate ();
}
DoInsert (insertItem, causesValidation);
}
public virtual void UpdateItem (int itemIndex, bool causesValidation)
{
if (itemIndex < 0)
throw new InvalidOperationException ("itemIndex is less than 0.");
IList <ListViewDataItem> items = Items;
if (itemIndex > items.Count)
return;
if (causesValidation) {
Page page = Page;
if (page != null)
page.Validate ();
}
DoUpdate (items [itemIndex], itemIndex, causesValidation);
}
protected virtual void InstantiateEmptyDataTemplate (Control container)
{
if (_emptyDataTemplate != null)
_emptyDataTemplate.InstantiateIn (container);
}
protected virtual void InstantiateEmptyItemTemplate (Control container)
{
if (_emptyItemTemplate != null)
_emptyItemTemplate.InstantiateIn (container);
}
protected virtual void InstantiateGroupSeparatorTemplate (Control container)
{
if (_groupSeparatorTemplate != null)
_groupSeparatorTemplate.InstantiateIn (container);
}
protected virtual void InstantiateGroupTemplate (Control container)
{
if (_groupTemplate != null)
_groupTemplate.InstantiateIn (container);
}
protected virtual void InstantiateInsertItemTemplate (Control container)
{
if (_insertItemTemplate != null)
_insertItemTemplate.InstantiateIn (container);
}
protected virtual void InstantiateItemSeparatorTemplate (Control container)
{
if (_itemSeparatorTemplate != null)
_itemSeparatorTemplate.InstantiateIn (container);
}
protected virtual void InstantiateItemTemplate (Control container, int displayIndex)
{
if (_itemTemplate == null)
throw new InvalidOperationException ("ItemTemplate is missing");
ITemplate template = _itemTemplate;
if (_alternatingItemTemplate != null && (displayIndex % 2 != 0))
template = _alternatingItemTemplate;
if (_selectedItemTemplate != null && (displayIndex == _selectedIndex))
template = _selectedItemTemplate;
if (_editItemTemplate != null && (displayIndex == _editIndex))
template = _editItemTemplate;
template.InstantiateIn (container);
}
void LoadDataKeysState (object savedState)
{
object[] state = savedState as object[];
int len = state != null ? state.Length : 0;
if (len == 0)
return;
ArrayList dataKeyArray = DataKeyArray;
DataKey dk;
string[] keyNames = DataKeyNames;
for (int i = 0; i < len; i++) {
dk = new DataKey (new OrderedDictionary (), keyNames);
((IStateManager)dk).LoadViewState (state [i]);
dataKeyArray.Add (dk);
}
_dataKeys = null;
}
protected override void LoadControlState (object savedState)
{
ResetDefaults ();
object[] state = savedState as object[];
if (state == null || state.Length != CSTATE_COUNT)
return;
object o;
base.LoadControlState (state [CSTATE_BASE_STATE]);
if ((o = state [CSTATE_DATAKEYNAMES]) != null)
DataKeyNames = (string[])o;
LoadDataKeysState (state [CSTATE_DATAKEYSSTATE]);
if ((o = state [CSTATE_GROUPITEMCOUNT]) != null)
GroupItemCount = (int)o;
if ((o = state [CSTATE_TOTALROWCOUNT]) != null)
_totalRowCount = (int)o;
if ((o = state [CSTATE_EDITINDEX]) != null)
EditIndex = (int)o;
if ((o = state [CSTATE_SELECTEDINDEX]) != null)
SelectedIndex = (int)o;
if ((o = state [CSTATE_SORTDIRECTION]) != null)
_sortDirection = (SortDirection)o;
if ((o = state [CSTATE_SORTEXPRESSION]) != null)
_sortExpression = (string)o;
OnTotalRowCountAvailable (new PageEventArgs (_startRowIndex, _maximumRows, _totalRowCount));
}
protected override void LoadViewState (object savedState)
{
object[] state = savedState as object[];
int len = state != null ? state.Length : 0;
if (len == 0)
return;
base.LoadViewState (state [0]);
object[] values = state [0] as object[];
if (values == null || values.Length == 0)
return;
Pair pair;
IOrderedDictionary currentEditOldValues = CurrentEditOldValues;
currentEditOldValues.Clear ();
foreach (object value in values) {
pair = value as Pair;
if (pair == null)
continue;
currentEditOldValues.Add (pair.First, pair.Second);
}
}
protected override bool OnBubbleEvent (object source, EventArgs e)
{
ListViewCommandEventArgs args = e as ListViewCommandEventArgs;
if (args == null)
args = new ListViewCommandEventArgs (CreateItem (ListViewItemType.EmptyItem), source, e as CommandEventArgs);
if (args != null) {
bool causesValidation = false;
IButtonControl button = args.CommandSource as IButtonControl;
if (button != null && button.CausesValidation) {
Page.Validate (button.ValidationGroup);
causesValidation = true;
}
ProcessCommand (args, causesValidation);
return true;
}
return base.OnBubbleEvent (source, e);
}
void ProcessCommand (ListViewCommandEventArgs args, bool causesValidation)
{
OnItemCommand (args);
string commandName = args.CommandName;
string commandArgument = args.CommandArgument as string;
if (String.Compare (commandName, DataControlCommands.SortCommandName, StringComparison.OrdinalIgnoreCase) == 0)
Sort (commandArgument, DetermineSortDirection (commandArgument));
else if (String.Compare (commandName, DataControlCommands.EditCommandName, StringComparison.OrdinalIgnoreCase) == 0)
DoEdit (args);
else if (String.Compare (commandName, DataControlCommands.CancelCommandName, StringComparison.OrdinalIgnoreCase) == 0)
DoCancel (args);
else if (String.Compare (commandName, DataControlCommands.DeleteCommandName, StringComparison.OrdinalIgnoreCase) == 0)
DoDelete (args);
else if (String.Compare (commandName, DataControlCommands.InsertCommandName, StringComparison.OrdinalIgnoreCase) == 0)
DoInsert (args, causesValidation);
else if (String.Compare (commandName, DataControlCommands.SelectCommandName, StringComparison.OrdinalIgnoreCase) == 0)
DoSelect (args);
else if (String.Compare (commandName, DataControlCommands.UpdateCommandName, StringComparison.OrdinalIgnoreCase) == 0) {
if (causesValidation) {
Page page = Page;
if (page != null && !page.IsValid)
return;
}
DoUpdate (args, causesValidation);
}
}
int GetItemIndex (ListViewDataItem item)
{
if (item == null)
return -1;
int index = item.DisplayIndex;
if (index < 0)
return -1;
return index;
}
void DoSelect (ListViewCommandEventArgs args)
{
ListViewDataItem item = args.Item as ListViewDataItem;
int index = GetItemIndex (item);
if (index < 0)
return;
var selectingArgs = new ListViewSelectEventArgs (index);
OnSelectedIndexChanging (selectingArgs);
if (selectingArgs.Cancel)
return;
SelectedIndex = selectingArgs.NewSelectedIndex;
OnSelectedIndexChanged (EventArgs.Empty);
}
void DoInsert (ListViewCommandEventArgs args, bool causesValidation)
{
ListViewItem item = args.Item as ListViewItem;
if (item == null)
return;
DoInsert (item, causesValidation);
}
void DoInsert (ListViewItem item, bool causesValidation)
{
if (causesValidation) {
Page page = Page;
if (page != null && !page.IsValid)
return;
}
DataSourceView view;
ListViewInsertEventArgs insertingArgs;
bool usingDataSourceID = IsBoundUsingDataSourceID;
if (usingDataSourceID) {
view = GetData ();
if (view == null)
throw NoDataSourceView ();
insertingArgs = new ListViewInsertEventArgs (item);
ExtractItemValues (insertingArgs.Values, item, true);
} else {
view = null;
insertingArgs = new ListViewInsertEventArgs (item);
}
OnItemInserting (insertingArgs);
if (!usingDataSourceID || insertingArgs.Cancel)
return;
_lastInsertValues = insertingArgs.Values;
view.Insert (_lastInsertValues, DoInsertCallback);
}
bool DoInsertCallback (int recordsAffected, Exception ex)
{
var insertedArgs = new ListViewInsertedEventArgs (recordsAffected, ex, _lastInsertValues);
OnItemInserted (insertedArgs);
_lastInsertValues = null;
// This will effectively reset the insert values
if (!insertedArgs.KeepInInsertMode)
RequiresDataBinding = true;
return insertedArgs.ExceptionHandled;
}
static InvalidOperationException NoDataSourceView ()
{
return new InvalidOperationException ("DataSourceView associated with the ListView is null.");
}
InvalidOperationException NoPlaceholder (bool group)
{
return new InvalidOperationException (
String.Format ("A{0} {1} placeholder must be specified on ListView '{2}'. Specify a{0} {1} placeholder by setting a control's ID property to \"{3}\". The {1} placeholder control must also specify runat=\"server\".",
group ? "" : "n",
group ? "group" : "item",
ID,
group ? GroupPlaceholderID : ItemPlaceholderID));
}
void DoDelete (ListViewCommandEventArgs args)
{
ListViewDataItem item = args.Item as ListViewDataItem;
int index = GetItemIndex (item);
if (index < 0)
return;
DoDelete (item, index);
}
void DoDelete (ListViewDataItem item, int index)
{
bool usingDataSourceID = IsBoundUsingDataSourceID;
var deletingArgs = new ListViewDeleteEventArgs (index);
if (usingDataSourceID) {
DataKeyArray dka = DataKeys;
if (index < dka.Count)
dka [index].Values.CopyTo (deletingArgs.Keys);
ExtractItemValues (deletingArgs.Values, item, true);
}
OnItemDeleting (deletingArgs);
if (!usingDataSourceID || deletingArgs.Cancel)
return;
DataSourceView view = GetData ();
if (view == null)
throw NoDataSourceView ();
_currentDeletingItemKeys = deletingArgs.Keys;
_currentDeletingItemValues = deletingArgs.Values;
view.Delete (_currentDeletingItemKeys, _currentDeletingItemValues, DoDeleteCallback);
}
bool DoDeleteCallback (int affectedRows, Exception exception)
{
var args = new ListViewDeletedEventArgs (affectedRows, exception, _currentDeletingItemKeys, _currentDeletingItemValues);
OnItemDeleted (args);
EditIndex = -1;
RequiresDataBinding = true;
return args.ExceptionHandled;
}
void DoUpdate (ListViewCommandEventArgs args, bool causesValidation)
{
ListViewDataItem item = args.Item as ListViewDataItem;
int index = GetItemIndex (item);
if (index < 0)
return;
DoUpdate (item, index, causesValidation);
}
void DoUpdate (ListViewDataItem item, int index, bool causesValidation)
{
if (causesValidation) {
Page page = Page;
if (page != null && !page.IsValid)
return;
}
bool usingDataSourceID = IsBoundUsingDataSourceID;
var updatingArgs = new ListViewUpdateEventArgs (index);
if (usingDataSourceID) {
DataKeyArray dka = DataKeys;
if (index < dka.Count)
dka [index].Values.CopyTo (updatingArgs.Keys);
CurrentEditOldValues.CopyTo (updatingArgs.OldValues);
ExtractItemValues (updatingArgs.NewValues, item, true);
}
OnItemUpdating (updatingArgs);
if (!usingDataSourceID || updatingArgs.Cancel)
return;
DataSourceView view = GetData ();
if (view == null)
throw NoDataSourceView ();
_currentEditOldValues = updatingArgs.OldValues;
_currentEditNewValues = updatingArgs.NewValues;
view.Update (updatingArgs.Keys, _currentEditNewValues, _currentEditOldValues, DoUpdateCallback);
}
bool DoUpdateCallback (int affectedRows, Exception exception)
{
var args = new ListViewUpdatedEventArgs (affectedRows, exception, _currentEditNewValues, _currentEditOldValues);
OnItemUpdated (args);
if (!args.KeepInEditMode) {
EditIndex = -1;
RequiresDataBinding = true;
_currentEditOldValues = null;
_currentEditNewValues = null;
}
return args.ExceptionHandled;
}
void DoCancel (ListViewCommandEventArgs args)
{
ListViewDataItem item = args.Item as ListViewDataItem;
int index = GetItemIndex (item);
if (index < 0)
return;
ListViewCancelMode cancelMode;
if (index == EditIndex)
cancelMode = ListViewCancelMode.CancelingEdit;
else if (item.ItemType == ListViewItemType.InsertItem)
cancelMode = ListViewCancelMode.CancelingInsert;
else
throw new InvalidOperationException ("Item being cancelled is neither an edit item or insert item.");
var cancelArgs = new ListViewCancelEventArgs (index, cancelMode);
OnItemCanceling (cancelArgs);
if (cancelArgs.Cancel)
return;
if (cancelMode == ListViewCancelMode.CancelingEdit)
EditIndex = -1;
RequiresDataBinding = true;
}
void DoEdit (ListViewCommandEventArgs args)
{
int index = GetItemIndex (args.Item as ListViewDataItem);
if (index < 0)
return;
var editArgs = new ListViewEditEventArgs (index);
OnItemEditing (editArgs);
if (editArgs.Cancel)
return;
if (IsBoundUsingDataSourceID)
EditIndex = index;
RequiresDataBinding = true;
}
SortDirection DetermineSortDirection (string sortExpression)
{
SortDirection ret;
if (sortExpression != SortExpression)
return SortDirection.Ascending;
if (SortDirection == SortDirection.Ascending)
ret = SortDirection.Descending;
else
ret = SortDirection.Ascending;
return ret;
}
protected override void OnInit (EventArgs e)
{
Page.RegisterRequiresControlState (this);
base.OnInit (e);
}
void InvokeEvent <T> (object key, T args) where T : EventArgs
{
EventHandlerList events = Events;
if (events != null) {
EventHandler <T> eh = events [key] as EventHandler <T>;
if (eh != null)
eh (this, args);
}
}
void InvokeEvent (object key, EventArgs args)
{
EventHandlerList events = Events;
if (events != null) {
EventHandler eh = events [key] as EventHandler;
if (eh != null)
eh (this, args);
}
}
protected virtual void OnItemCanceling (ListViewCancelEventArgs e)
{
InvokeEvent <ListViewCancelEventArgs> (ItemCancellingEvent, e);
}
protected virtual void OnItemCommand (ListViewCommandEventArgs e)
{
InvokeEvent <ListViewCommandEventArgs> (ItemCommandEvent, e);
}
protected virtual void OnItemCreated (ListViewItemEventArgs e)
{
InvokeEvent <ListViewItemEventArgs> (ItemCreatedEvent, e);
}
protected virtual void OnItemDataBound (ListViewItemEventArgs e)
{
InvokeEvent <ListViewItemEventArgs> (ItemDataBoundEvent, e);
}
protected virtual void OnItemDeleted (ListViewDeletedEventArgs e)
{
InvokeEvent <ListViewDeletedEventArgs> (ItemDeletedEvent, e);
}
protected virtual void OnItemDeleting (ListViewDeleteEventArgs e)
{
InvokeEvent <ListViewDeleteEventArgs> (ItemDeletingEvent, e);
}
protected virtual void OnItemEditing (ListViewEditEventArgs e)
{
InvokeEvent <ListViewEditEventArgs> (ItemEditingEvent, e);
}
protected virtual void OnItemInserted (ListViewInsertedEventArgs e)
{
InvokeEvent <ListViewInsertedEventArgs> (ItemInsertedEvent, e);
}
protected virtual void OnItemInserting (ListViewInsertEventArgs e)
{
InvokeEvent <ListViewInsertEventArgs> (ItemInsertingEvent, e);
}
protected virtual void OnItemUpdated (ListViewUpdatedEventArgs e)
{
InvokeEvent <ListViewUpdatedEventArgs> (ItemUpdatedEvent, e);
}
protected virtual void OnItemUpdating (ListViewUpdateEventArgs e)
{
InvokeEvent <ListViewUpdateEventArgs> (ItemUpdatingEvent, e);
}
protected virtual void OnLayoutCreated (EventArgs e)
{
InvokeEvent (LayoutCreatedEvent, e);
}
protected virtual void OnPagePropertiesChanged (EventArgs e)
{
InvokeEvent (PagePropertiesChangedEvent, e);
}
protected virtual void OnPagePropertiesChanging (PagePropertiesChangingEventArgs e)
{
InvokeEvent (PagePropertiesChangingEvent, e);
}
protected virtual void OnSelectedIndexChanged (EventArgs e)
{
InvokeEvent (SelectedIndexChangedEvent, e);
}
protected virtual void OnSelectedIndexChanging (ListViewSelectEventArgs e)
{
InvokeEvent (SelectedIndexChangingEvent, e);
}
protected virtual void OnSorted (EventArgs e)
{
InvokeEvent (SortedEvent, e);
}
protected virtual void OnSorting (ListViewSortEventArgs e)
{
InvokeEvent <ListViewSortEventArgs> (SortingEvent, e);
}
protected virtual void OnTotalRowCountAvailable (PageEventArgs e)
{
InvokeEvent <PageEventArgs> (TotalRowCountAvailableEvent, e);
}
protected override void PerformDataBinding (IEnumerable data)
{
base.PerformDataBinding (data);
TrackViewState ();
if (IsBoundUsingDataSourceID) {
int editIndex = EditIndex;
IList <ListViewDataItem> items = Items;
if (editIndex > 0 && editIndex < items.Count) {
CurrentEditOldValues.Clear ();
ExtractItemValues (CurrentEditOldValues, items [editIndex], true);
}
}
int childCount = CreateChildControls (data, true);
ChildControlsCreated = true;
ViewState ["_!ItemCount"] = childCount;
}
protected override void PerformSelect ()
{
EnsureLayoutTemplate ();
base.PerformSelect ();
}
protected virtual void RemoveItems ()
{
if (_nonGroupedItemsContainer != null)
RemoveItems (_nonGroupedItemsContainer, _nonGroupedItemsContainerFirstItemIndex, _nonGroupedItemsContainerItemCount);
if (_groupedItemsContainer != null)
RemoveItems (_groupedItemsContainer, _groupedItemsContainerPlaceholderIndex, _groupedItemsContainerItemCount);
}
void RemoveItems (Control container, int start, int count)
{
int i = count;
while (i-- > 0)
container.Controls.RemoveAt (start);
}
protected override void Render (HtmlTextWriter writer)
{
base.Render (writer);
// Why override?
}
object SaveDataKeysState ()
{
DataKeyArray dka = DataKeys;
int len = dka != null ? dka.Count : 0;
if (len == 0)
return null;
object[] state = new object [len];
DataKey dk;
for (int i = 0; i < len; i++) {
dk = dka [i];
if (dk == null) {
state [i] = null;
continue;
}
state [i] = ((IStateManager)dk).SaveViewState ();
}
return state;
}
protected override object SaveControlState ()
{
object[] ret = new object [CSTATE_COUNT];
string[] dataKeyNames = DataKeyNames;
object dataKeysState = SaveDataKeysState ();
ret [CSTATE_BASE_STATE] = base.SaveControlState ();
ret [CSTATE_DATAKEYNAMES] = dataKeyNames.Length > 0 ? dataKeyNames : null;
ret [CSTATE_DATAKEYSSTATE] = dataKeysState != null ? dataKeysState : null;
ret [CSTATE_GROUPITEMCOUNT] = _groupItemCount > 1 ? (object)_groupItemCount : null;
ret [CSTATE_TOTALROWCOUNT] = _totalRowCount >= 1 ? (object)_totalRowCount : null;
ret [CSTATE_EDITINDEX] = _editIndex != -1 ? (object)_editIndex : null;
ret [CSTATE_SELECTEDINDEX] = _selectedIndex != -1 ? (object)_selectedIndex : null;
ret [CSTATE_SORTDIRECTION] = _sortDirection != SortDirection.Ascending ? (object)_sortDirection : null;
ret [CSTATE_SORTEXPRESSION] = String.IsNullOrEmpty (_sortExpression) ? null : _sortExpression;
return ret;
}
object SaveCurrentEditOldValues ()
{
IOrderedDictionary values = CurrentEditOldValues;
int count = values.Count;
if (count == 0)
return null;
object[] ret = new object [count];
DictionaryEntry entry;
int i = -1;
foreach (object o in values) {
i++;
entry = (DictionaryEntry)o;
ret [i] = new Pair (entry.Key, entry.Value);
}
return ret;
}
protected override object SaveViewState ()
{
object[] states = new object [2];
states [0] = base.SaveViewState ();
states [1] = SaveCurrentEditOldValues ();
return states;
}
protected virtual void SetPageProperties (int startRowIndex, int maximumRows, bool databind)
{
if (maximumRows < 1)
throw new ArgumentOutOfRangeException ("maximumRows");
if (startRowIndex < 0)
throw new ArgumentOutOfRangeException ("startRowIndex");
if (maximumRows != _maximumRows || startRowIndex != _startRowIndex) {
if (databind) {
var args = new PagePropertiesChangingEventArgs (startRowIndex, maximumRows);
OnPagePropertiesChanging (args);
_startRowIndex = args.StartRowIndex;
_maximumRows = args.MaximumRows;
} else {
_startRowIndex = startRowIndex;
_maximumRows = maximumRows;
}
if (databind)
OnPagePropertiesChanged (EventArgs.Empty);
}
if (databind)
RequiresDataBinding = true;
}
public virtual void Sort (string sortExpression, SortDirection sortDirection)
{
ListViewSortEventArgs args = new ListViewSortEventArgs (sortExpression, sortDirection);
OnSorting (args);
if (args.Cancel)
return;
if (IsBoundUsingDataSourceID) {
DataSourceView dsv = GetData ();
if (dsv == null)
throw new InvalidOperationException ("Missing data.");
_sortDirection = args.SortDirection;
_sortExpression = args.SortExpression;
_startRowIndex = 0;
EditIndex = -1;
}
OnSorted (EventArgs.Empty);
RequiresDataBinding = true;
}
void IPageableItemContainer.SetPageProperties (int startRowIndex, int maximumRows, bool databind)
{
SetPageProperties (startRowIndex, maximumRows, databind);
}
NotSupportedException StylingNotSupported ()
{
return new NotSupportedException ("Style properties are not supported on ListView. Apply styling or CSS classes to the elements in the ListView's templates.");
}
}
}
#endif
|