using System.Drawing;
using System.Runtime.InteropServices;
using System.Globalization;
-#if NET_2_0
using System.Collections.Generic;
-#endif
namespace System.Windows.Forms
{
[DefaultEvent ("SelectedIndexChanged")]
[DefaultProperty ("Items")]
[Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
-#if NET_2_0
[ClassInterface (ClassInterfaceType.AutoDispatch)]
[ComVisible (true)]
[Docking (DockingBehavior.Ask)]
-#endif
public class ListView : Control
{
private ItemActivation activation = ItemActivation.Standard;
private bool hover_selection;
private IComparer item_sorter;
private readonly ListViewItemCollection items;
-#if NET_2_0
private readonly ListViewGroupCollection groups;
private bool owner_draw;
private bool show_groups = true;
-#endif
private bool label_edit;
private bool label_wrap = true;
private bool multiselect = true;
private Size item_size; // used for caching item size
private int custom_column_width; // used when using Columns with SmallIcon/List views
private int hot_item_index = -1;
-#if NET_2_0
private bool hot_tracking;
private ListViewInsertionMark insertion_mark;
private bool show_item_tooltips;
private bool virtual_mode;
private int virtual_list_size;
private bool right_to_left_layout;
-#endif
+ // selection is available after the first time the handle is created, *even* if later
+ // the handle is either recreated or destroyed - so keep this info around.
+ private bool is_selection_available;
// internal variables
internal ImageList large_image_list;
static object ItemCheckEvent = new object ();
static object ItemDragEvent = new object ();
static object SelectedIndexChangedEvent = new object ();
-#if NET_2_0
static object DrawColumnHeaderEvent = new object();
static object DrawItemEvent = new object();
static object DrawSubItemEvent = new object();
static object RightToLeftLayoutChangedEvent = new object ();
static object SearchForVirtualItemEvent = new object ();
static object VirtualItemsSelectionRangeChangedEvent = new object ();
-#endif
public event LabelEditEventHandler AfterLabelEdit {
add { Events.AddHandler (AfterLabelEditEvent, value); }
remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
}
-#if !NET_2_0
- [Browsable (false)]
- [EditorBrowsable (EditorBrowsableState.Never)]
- public new event EventHandler BackgroundImageChanged {
- add { base.BackgroundImageChanged += value; }
- remove { base.BackgroundImageChanged -= value; }
- }
-#endif
-#if NET_2_0
[Browsable (false)]
[EditorBrowsable (EditorBrowsableState.Never)]
public new event EventHandler BackgroundImageLayoutChanged {
add { base.BackgroundImageLayoutChanged += value; }
remove { base.BackgroundImageLayoutChanged -= value; }
}
-#endif
public event LabelEditEventHandler BeforeLabelEdit {
add { Events.AddHandler (BeforeLabelEditEvent, value); }
remove { Events.RemoveHandler (ColumnClickEvent, value); }
}
-#if NET_2_0
public event DrawListViewColumnHeaderEventHandler DrawColumnHeader {
add { Events.AddHandler(DrawColumnHeaderEvent, value); }
remove { Events.RemoveHandler(DrawColumnHeaderEvent, value); }
add { Events.AddHandler(DrawSubItemEvent, value); }
remove { Events.RemoveHandler(DrawSubItemEvent, value); }
}
-#endif
public event EventHandler ItemActivate {
add { Events.AddHandler (ItemActivateEvent, value); }
remove { Events.RemoveHandler (ItemCheckEvent, value); }
}
-#if NET_2_0
public event ItemCheckedEventHandler ItemChecked {
add { Events.AddHandler (ItemCheckedEvent, value); }
remove { Events.RemoveHandler (ItemCheckedEvent, value); }
}
-#endif
public event ItemDragEventHandler ItemDrag {
add { Events.AddHandler (ItemDragEvent, value); }
remove { Events.RemoveHandler (ItemDragEvent, value); }
}
-#if NET_2_0
public event ListViewItemMouseHoverEventHandler ItemMouseHover {
add { Events.AddHandler (ItemMouseHoverEvent, value); }
remove { Events.RemoveHandler (ItemMouseHoverEvent, value); }
add { base.PaddingChanged += value; }
remove { base.PaddingChanged -= value; }
}
-#endif
[Browsable (false)]
[EditorBrowsable (EditorBrowsableState.Never)]
remove { base.TextChanged -= value; }
}
-#if NET_2_0
public event CacheVirtualItemsEventHandler CacheVirtualItems {
add { Events.AddHandler (CacheVirtualItemsEvent, value); }
remove { Events.RemoveHandler (CacheVirtualItemsEvent, value); }
add { Events.AddHandler (VirtualItemsSelectionRangeChangedEvent, value); }
remove { Events.RemoveHandler (VirtualItemsSelectionRangeChangedEvent, value); }
}
-#endif
#endregion // Events
public ListView ()
{
background_color = ThemeEngine.Current.ColorWindow;
-#if NET_2_0
groups = new ListViewGroupCollection (this);
-#endif
items = new ListViewItemCollection (this);
items.Changed += new CollectionChangedHandler (OnItemsChanged);
checked_indices = new CheckedIndexCollection (this);
items_location = new Point [16];
items_matrix_location = new ItemMatrixLocation [16];
reordered_items_indices = new int [16];
-#if NET_2_0
item_tooltip = new ToolTip ();
item_tooltip.Active = false;
insertion_mark = new ListViewInsertionMark (this);
-#endif
InternalBorderStyle = BorderStyle.Fixed3D;
MouseEnter += new EventHandler (ListView_MouseEnter);
Invalidated += new InvalidateEventHandler (ListView_Invalidated);
-#if NET_2_0
BackgroundImageTiled = false;
-#endif
this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
-#if NET_2_0
| ControlStyles.UseTextForAccessibility
-#endif
, false);
}
#endregion // Public Constructors
}
}
-#if NET_2_0
internal bool UsingGroups {
get {
return show_groups && groups.Count > 0 && view != View.List &&
Application.VisualStylesEnabled;
}
}
-#endif
internal override bool ScaleChildrenInternal {
get { return false; }
protected override Size DefaultSize {
get { return ThemeEngine.Current.ListViewDefaultSize; }
}
-#if NET_2_0
protected override bool DoubleBuffered {
get {
return base.DoubleBuffered;
base.DoubleBuffered = value;
}
}
-#endif
#endregion // Protected Properties
#region Public Instance Properties
throw new InvalidEnumArgumentException (string.Format
("Enum argument value '{0}' is not valid for Activation", value));
}
-#if NET_2_0
if (hot_tracking && value != ItemActivation.OneClick)
throw new ArgumentException ("When HotTracking is on, activation must be ItemActivation.OneClick");
-#endif
activation = value;
}
}
}
-#if !NET_2_0
- [Browsable (false)]
- [EditorBrowsable (EditorBrowsableState.Never)]
- public override Image BackgroundImage {
- get { return base.BackgroundImage; }
- set { base.BackgroundImage = value; }
- }
-#endif
-
-#if NET_2_0
[Browsable (false)]
[EditorBrowsable (EditorBrowsableState.Never)]
public override ImageLayout BackgroundImageLayout {
item_control.BackgroundImageLayout = new_image_layout;
}
}
-#endif
[DefaultValue (BorderStyle.Fixed3D)]
[DispId (-504)]
get { return check_boxes; }
set {
if (check_boxes != value) {
-#if NET_2_0
if (value && View == View.Tile)
throw new NotSupportedException ("CheckBoxes are not"
+ " supported in Tile view. Choose a different"
+ " view or set CheckBoxes to false.");
-#endif
check_boxes = value;
this.Redraw (true);
-#if NET_2_0
//UIA Framework: Event used by ListView to set/unset Toggle Pattern
OnUIACheckBoxesChanged ();
-#endif
}
}
}
get { return checked_items; }
}
-#if NET_2_0
[Editor ("System.Windows.Forms.Design.ColumnHeaderCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
-#endif
[DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
[Localizable (true)]
[MergableProperty (false)]
return GetItemAtDisplayIndex (focused_item_index);
}
-#if NET_2_0
set {
if (value == null || value.ListView != this ||
!IsHandleCreated)
SetFocusedItem (value.DisplayIndex);
}
-#endif
}
public override Color ForeColor {
}
}
-#if NET_2_0
[DefaultValue (false)]
public bool HotTracking {
get {
}
}
}
-#endif
[DefaultValue (false)]
public bool HoverSelection {
get { return hover_selection; }
set {
-#if NET_2_0
if (hot_tracking && value == false)
throw new ArgumentException ("When HotTracking is on, hover selection must be true");
-#endif
hover_selection = value;
}
}
-#if NET_2_0
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
public ListViewInsertionMark InsertionMark {
return insertion_mark;
}
}
-#endif
-#if NET_2_0
[Editor ("System.Windows.Forms.Design.ListViewItemCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
-#endif
[DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
[Localizable (true)]
[MergableProperty (false)]
if (value != label_edit) {
label_edit = value;
-#if NET_2_0
// UIA Framework: Event used by Value Pattern in ListView.ListItem provider
OnUIALabelEditChanged ();
-#endif
}
}
if (value != multiselect) {
multiselect = value;
-#if NET_2_0
// UIA Framework: Event used by Selection Pattern in ListView.ListItem provider
OnUIAMultiSelectChanged ();
-#endif
}
}
}
-#if NET_2_0
[DefaultValue(false)]
public bool OwnerDraw {
get { return owner_draw; }
}
}
}
-#endif
[DefaultValue (true)]
public bool Scrollable {
get { return selected_items; }
}
-#if NET_2_0
[DefaultValue(true)]
public bool ShowGroups {
get { return show_groups; }
item_tooltip.Active = false;
}
}
-#endif
[DefaultValue (null)]
public ImageList SmallImageList {
sort_order = value;
-#if NET_2_0
if (virtual_mode) // Sorting is not allowed in virtual mode
return;
-#endif
if (value == SortOrder.None) {
if (item_sorter != null) {
// ListViewItemSorter should never be reset for SmallIcon
// and LargeIcon view
if (View != View.SmallIcon && View != View.LargeIcon)
-#if NET_2_0
item_sorter = null;
-#else
- // in .NET 1.1, only internal IComparer would be
- // set to null
- if (item_sorter is ItemComparer)
- item_sorter = null;
-#endif
}
this.Redraw (false);
} else {
if (item_sorter == null)
item_sorter = new ItemComparer (value);
if (item_sorter is ItemComparer) {
-#if NET_2_0
item_sorter = new ItemComparer (value);
-#else
- // in .NET 1.1, the sort order is not updated for
- // SmallIcon and LargeIcon views if no custom IComparer
- // is set
- if (View != View.SmallIcon && View != View.LargeIcon)
- item_sorter = new ItemComparer (value);
-#endif
}
Sort ();
}
}
}
-#if NET_2_0
[Browsable (true)]
public Size TileSize {
get {
Redraw (true);
}
}
-#endif
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public ListViewItem TopItem {
get {
-#if NET_2_0
if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
throw new InvalidOperationException ("Cannot get the top item in LargeIcon, SmallIcon or Tile view.");
-#endif
// there is no item
if (this.items.Count == 0)
return null;
return this.items [0];
// do a hit test for the scrolled position
else {
+ int header_offset = header_control.Height;
for (int i = 0; i < items.Count; i++) {
Point item_loc = GetItemLocation (i);
- if (item_loc.X >= 0 && item_loc.Y >= 0)
+ if (item_loc.X >= 0 && item_loc.Y - header_offset >= 0)
return items [i];
}
return null;
}
}
-#if NET_2_0
set {
if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
throw new InvalidOperationException ("Cannot set the top item in LargeIcon, SmallIcon or Tile view.");
if (value == null || value.ListView != this)
return;
- EnsureVisible (value.Index);
+ // Take advantage this property is only valid for Details view.
+ SetScrollValue (v_scroll, item_size.Height * value.Index);
}
-#endif
}
-#if NET_2_0
[EditorBrowsable (EditorBrowsableState.Advanced)]
[DefaultValue (true)]
[Browsable (false)]
set {
}
}
-#endif
[DefaultValue (View.LargeIcon)]
public View View {
typeof (View));
if (view != value) {
-#if NET_2_0
if (CheckBoxes && value == View.Tile)
throw new NotSupportedException ("CheckBoxes are not"
+ " supported in Tile view. Choose a different"
+ " view or set CheckBoxes to false.");
-#endif
+ if (VirtualMode && value == View.Tile)
+ throw new NotSupportedException ("VirtualMode is"
+ + " not supported in Tile view. Choose a different"
+ + " view or set ViewMode to false.");
h_scroll.Value = v_scroll.Value = 0;
view = value;
Redraw (true);
-#if NET_2_0
// UIA Framework: Event used to update UIA Tree.
OnUIAViewChanged ();
-#endif
}
}
}
-#if NET_2_0
[DefaultValue (false)]
[RefreshProperties (RefreshProperties.Repaint)]
public bool VirtualMode {
if (!virtual_mode && items.Count > 0)
throw new InvalidOperationException ();
+ if (value && view == View.Tile)
+ throw new NotSupportedException ("VirtualMode is"
+ + " not supported in Tile view. Choose a different"
+ + " view or set ViewMode to false.");
virtual_mode = value;
Redraw (true);
}
}
}
-#endif
#endregion // Public Instance Properties
#region Internal Methods Properties
return 0;
Size item_size = ItemSize;
+ // In virtual mode we always have fixed positions, and we can infer the positon easily
+ if (virtual_mode) {
+ int first = 0;
+ switch (view) {
+ case View.Details:
+ first = v_marker / item_size.Height;
+ break;
+ case View.LargeIcon:
+ case View.SmallIcon:
+ first = (v_marker / (item_size.Height + y_spacing)) * cols;
+ break;
+ case View.List:
+ first = (h_marker / (item_size.Width * x_spacing)) * rows;
+ break;
+ }
+
+ if (first >= items.Count)
+ first = items.Count;
+
+ return first;
+ }
for (int i = 0; i < items.Count; i++) {
Rectangle item_rect = new Rectangle (GetItemLocation (i), item_size);
if (item_rect.Right >= 0 && item_rect.Bottom >= 0)
internal void OnSelectedIndexChanged ()
{
- if (IsHandleCreated)
+ if (is_selection_available)
OnSelectedIndexChanged (EventArgs.Empty);
}
// Avoid calculations when control is being updated
if (updating)
return;
-#if NET_2_0
// VirtualMode doesn't do any calculations until handle is created
if (virtual_mode && !IsHandleCreated)
return;
-#endif
if (recalculate)
CalculateListView (this.alignment);
- Refresh ();
+ Invalidate (true);
}
void InvalidateSelection ()
{
Size temp = Size.Empty;
Size ret_size = Size.Empty;
-#if NET_2_0
bool use_indent_count = small_image_list != null;
// VirtualMode uses the first item text size
if (use_indent_count)
ret_size.Width += item.IndentCount * small_image_list.ImageSize.Width;
} else {
-#endif
// 0th column holds the item text, we check the size of
// the various subitems falling in that column and get
// the biggest one's size.
temp = Size.Ceiling (TextRenderer.MeasureString
(item.SubItems [col].Text, Font));
-#if NET_2_0
if (use_indent_count)
temp.Width += item.IndentCount * small_image_list.ImageSize.Width;
-#endif
if (temp.Width > ret_size.Width)
ret_size = temp;
}
-#if NET_2_0
}
-#endif
// adjustment for space in Details view
if (!ret_size.IsEmpty && view == View.Details)
text_size.Height += 2;
}
- private void Scroll (ScrollBar scrollbar, int delta)
+ private void SetScrollValue (ScrollBar scrollbar, int val)
{
- if (delta == 0 || !scrollbar.Visible)
- return;
-
int max;
if (scrollbar == h_scroll)
- max = h_scroll.Maximum - item_control.Width;
+ max = h_scroll.Maximum - h_scroll.LargeChange + 1;
else
- max = v_scroll.Maximum - item_control.Height;
+ max = v_scroll.Maximum - v_scroll.LargeChange + 1;
- int val = scrollbar.Value + delta;
if (val > max)
val = max;
else if (val < scrollbar.Minimum)
val = scrollbar.Minimum;
+
scrollbar.Value = val;
}
+ private void Scroll (ScrollBar scrollbar, int delta)
+ {
+ if (delta == 0 || !scrollbar.Visible)
+ return;
+
+ SetScrollValue (scrollbar, scrollbar.Value + delta);
+ }
+
private void CalculateScrollBars ()
{
Rectangle client_area = ClientRectangle;
int height = client_area.Height;
int width = client_area.Width;
+ Size item_size;
if (!scrollable) {
h_scroll.Visible = false;
}
+ item_size = ItemSize;
+
if (h_scroll.is_visible) {
h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
h_scroll.Minimum = 0;
h_scroll.Width = client_area.Width;
}
+ if (view == View.List)
+ h_scroll.SmallChange = item_size.Width + ThemeEngine.Current.ListViewHorizontalSpacing;
+ else
+ h_scroll.SmallChange = Font.Height;
+
h_scroll.LargeChange = client_area.Width;
- h_scroll.SmallChange = item_size.Width + ThemeEngine.Current.ListViewHorizontalSpacing;
height -= h_scroll.Height;
}
if (v_scroll.is_visible) {
v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
v_scroll.Minimum = 0;
- v_scroll.Maximum = layout_ht;
// if h_scroll is visible, adjust the height of
// v_scroll to account for the height of h_scroll
- if (h_scroll.Visible)
- v_scroll.Height = client_area.Height - h_scroll.Height;
- else
+ if (h_scroll.Visible) {
+ v_scroll.Maximum = layout_ht + h_scroll.Height;
+ v_scroll.Height = client_area.Height > h_scroll.Height ? client_area.Height - h_scroll.Height : 0;
+ } else {
+ v_scroll.Maximum = layout_ht;
v_scroll.Height = client_area.Height;
+ }
+
+ if (view == View.Details) {
+ // Need to update Maximum if using LargeChange with value other than the visible area
+ int headerPlusOneItem = header_control.Height + item_size.Height;
+ v_scroll.LargeChange = v_scroll.Height > headerPlusOneItem ? v_scroll.Height - headerPlusOneItem : 0;
+ v_scroll.Maximum = v_scroll.Maximum > headerPlusOneItem ? v_scroll.Maximum - headerPlusOneItem : 0;
+ } else
+ v_scroll.LargeChange = v_scroll.Height;
- v_scroll.LargeChange = client_area.Height;
- v_scroll.SmallChange = Font.Height;
+ v_scroll.SmallChange = item_size.Height;
width -= v_scroll.Width;
}
header_control.Width = width;
}
-#if NET_2_0
internal int GetReorderedColumnIndex (ColumnHeader column)
{
if (reordered_column_indices == null)
return -1;
}
-#endif
internal ColumnHeader GetReorderedColumn (int index)
{
internal void ReorderColumn (ColumnHeader col, int index, bool fireEvent)
{
-#if NET_2_0
if (fireEvent) {
ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
if (eh != null){
}
}
}
-#endif
int column_count = Columns.Count;
if (reordered_column_indices == null) {
}
}
-#if NET_2_0
Size TileItemSize {
get {
// Calculate tile size if needed
return tile_size;
}
}
-#endif
int GetDetailsItemHeight ()
{
reordered_items_indices [index] = index;
}
-#if NET_2_0
+
void ShiftItemsPositions (int from, int to, bool forward)
{
if (forward) {
return count;
}
-#endif
+ // cache the spacing to let virtualmode compute the positions on the fly
+ int x_spacing;
+ int y_spacing;
int rows;
int cols;
int[,] item_index_matrix;
if (UseCustomColumnWidth)
CalculateCustomColumnWidth ();
-#if NET_2_0
if (UsingGroups) {
// When groups are used the alignment is always top-aligned
rows = 0;
items += items_in_group;
}
} else
-#endif
{
// Simple matrix if no groups are used
if (left_aligned) {
item_control.Visible = true;
item_control.Location = Point.Empty;
ItemSize = item_size; // Cache item size
+ this.x_spacing = x_spacing;
+ this.y_spacing = y_spacing;
if (items.Count == 0)
return;
Size sz = item_size;
-#if NET_2_0
- bool using_groups = UsingGroups;
-#endif
CalculateRowsAndCols (sz, left_aligned, x_spacing, y_spacing);
layout_wd = UseCustomColumnWidth ? cols * custom_column_width : cols * (sz.Width + x_spacing) - x_spacing;
layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
-#if NET_2_0
- if (using_groups)
+
+ if (virtual_mode) { // no actual assignment is needed on items for virtual mode
+ item_control.Size = new Size (layout_wd, layout_ht);
+ return;
+ }
+
+ bool using_groups = UsingGroups;
+ if (using_groups) // the groups layout will override layout_ht
CalculateGroupsLayout (sz, y_spacing, 0);
-#endif
int row = 0, col = 0;
int x = 0, y = 0;
int display_index = 0;
for (int i = 0; i < items.Count; i++) {
-#if NET_2_0
+ ListViewItem item = items [i];
if (using_groups) {
- ListViewGroup group = items [i].Group;
+ ListViewGroup group = item.Group;
if (group == null)
group = groups.DefaultGroup;
item_index_matrix [row + starting_row, col] = i;
} else
-#endif
{
x = UseCustomColumnWidth ? col * custom_column_width : col * (item_size.Width + x_spacing);
y = row * (item_size.Height + y_spacing);
}
}
}
-#if NET_2_0
- if (!virtual_mode)
-#endif
- {
- ListViewItem item = items [i];
- item.Layout ();
- item.DisplayIndex = display_index;
-#if NET_2_0
- item.SetPosition (new Point (x, y));
-#endif
- }
-
+ item.Layout ();
+ item.DisplayIndex = display_index;
+ item.SetPosition (new Point (x, y));
}
item_control.Size = new Size (layout_wd, layout_ht);
}
-#if NET_2_0
void CalculateGroupsLayout (Size item_size, int y_spacing, int y_origin)
{
int y = y_origin;
int LayoutGroupHeader (ListViewGroup group, int y_origin, int item_height, int y_spacing, int rows)
{
Rectangle client_area = ClientRectangle;
- int header_height = text_size.Height + 10;
+ int header_height = Font.Height + 15; // one line height + some padding
group.HeaderBounds = new Rectangle (0, y_origin, client_area.Width - v_scroll.Width, header_height);
group.items_area_location = new Point (0, y_origin + header_height);
items += items_in_group;
}
}
-#endif
void LayoutHeader ()
{
item_control.Visible = true;
item_control.Location = Point.Empty;
item_control.Width = ClientRectangle.Width;
+ AdjustChildrenZOrder ();
int item_height = GetDetailsItemHeight ();
ItemSize = new Size (0, item_height); // We only cache Height for details view
int y = header_control.Height;
-#if NET_2_0
+ layout_ht = y + (item_height * items.Count);
+ if (items.Count > 0 && grid_lines) // some space for bottom gridline
+ layout_ht += 2;
+
bool using_groups = UsingGroups;
if (using_groups) {
+ // Observe that this routines will override our layout_ht value
CalculateDetailsGroupItemsCount ();
CalculateGroupsLayout (ItemSize, 2, y);
}
-#endif
+
+ if (virtual_mode) // no assgination on items is needed
+ return;
for (int i = 0; i < items.Count; i++) {
ListViewItem item = items [i];
+
int display_index;
-#if NET_2_0
+ int item_y;
+
if (using_groups) {
ListViewGroup group = item.Group;
if (group == null)
Point group_items_loc = group.items_area_location;
display_index = group.starting_item + current_item;
- y = current_item * (item_height + 2) + group_items_loc.Y;
- SetItemLocation (display_index, 0, y, 0, 0);
+ y = item_y = current_item * (item_height + 2) + group_items_loc.Y;
+ SetItemLocation (display_index, 0, item_y, 0, 0);
SetItemAtDisplayIndex (display_index, i);
- item.SetPosition (new Point (0, y));
} else
-#endif
{
display_index = i;
- SetItemLocation (i, 0, y, 0, 0);
-#if NET_2_0
- item.SetPosition (new Point (0, y));
-#endif
+ item_y = y;
+ SetItemLocation (i, 0, item_y, 0, 0);
y += item_height;
}
-#if NET_2_0
- if (!virtual_mode) // Virtual mode sets Layout until draw time
-#endif
- {
- item.Layout ();
- item.DisplayIndex = display_index;
- }
+ item.Layout ();
+ item.DisplayIndex = display_index;
+ item.SetPosition (new Point (0, item_y));
}
+ }
- // some space for bottom gridline
- if (items.Count > 0 && grid_lines)
- y += 2;
-
-#if NET_2_0
- if (!using_groups) // With groups it has been previously computed
-#endif
- layout_ht = y;
+ // Need to make sure HeaderControl is on top, and we can't simply use BringToFront since
+ // these controls are implicit, so we need to re-populate our collection.
+ void AdjustChildrenZOrder ()
+ {
+ SuspendLayout ();
+ Controls.ClearImplicit ();
+ Controls.AddImplicit (header_control);
+ Controls.AddImplicit (item_control);
+ Controls.AddImplicit (h_scroll);
+ Controls.AddImplicit (v_scroll);
+ ResumeLayout ();
}
private void AdjustItemsPositionArray (int count)
{
+ // In virtual mode we compute the positions on the fly.
+ if (virtual_mode)
+ return;
if (items_location.Length >= count)
return;
LayoutIcons (SmallIconItemSize, true,
ThemeEngine.Current.ListViewHorizontalSpacing, 2);
break;
-#if NET_2_0
case View.Tile:
if (!Application.VisualStylesEnabled)
goto case View.LargeIcon;
ThemeEngine.Current.ListViewHorizontalSpacing,
ThemeEngine.Current.ListViewVerticalSpacing);
break;
-#endif
}
CalculateScrollBars ();
internal Point GetItemLocation (int index)
{
- Point loc = items_location [index];
+ Point loc = Point.Empty;
+ if (virtual_mode)
+ loc = GetFixedItemLocation (index);
+ else
+ loc = items_location [index];
+
loc.X -= h_marker; // Adjust to scroll
loc.Y -= v_marker;
return loc;
}
+ Point GetFixedItemLocation (int index)
+ {
+ Point loc = Point.Empty;
+
+ switch (view) {
+ case View.LargeIcon:
+ case View.SmallIcon:
+ loc.X = index % cols * (item_size.Width + x_spacing);
+ loc.Y = index / cols * (item_size.Height + y_spacing);
+ break;
+ case View.List:
+ loc.X = index / rows * (item_size.Width + x_spacing);
+ loc.Y = index % rows * (item_size.Height + y_spacing);
+ break;
+ case View.Details:
+ loc.Y = header_control.Height + (index * item_size.Height);
+ break;
+ }
+
+ return loc;
+ }
+
internal int GetItemIndex (int display_index)
{
+ if (virtual_mode)
+ return display_index; // no reordering in virtual mode.
return reordered_items_indices [display_index];
}
internal ListViewItem GetItemAtDisplayIndex (int display_index)
{
+ // in virtual mode there's no reordering at all.
+ if (virtual_mode)
+ return items [display_index];
return items [reordered_items_indices [display_index]];
}
return result;
}
+ if (virtual_mode)
+ return GetFixedAdjustedIndex (key);
+
ItemMatrixLocation item_matrix_location = items_matrix_location [FocusedItem.DisplayIndex];
int row = item_matrix_location.Row;
int col = item_matrix_location.Col;
return items [adjusted_index].DisplayIndex;
}
+ // Used for virtual mode, where items *cannot* be re-arranged
+ int GetFixedAdjustedIndex (Keys key)
+ {
+ int result;
+
+ switch (key) {
+ case Keys.Left:
+ if (view == View.List)
+ result = focused_item_index - rows;
+ else
+ result = focused_item_index - 1;
+ break;
+ case Keys.Right:
+ if (view == View.List)
+ result = focused_item_index + rows;
+ else
+ result = focused_item_index + 1;
+ break;
+ case Keys.Up:
+ if (view != View.List)
+ result = focused_item_index - cols;
+ else
+ result = focused_item_index - 1;
+ break;
+ case Keys.Down:
+ if (view != View.List)
+ result = focused_item_index + cols;
+ else
+ result = focused_item_index + 1;
+ break;
+ default:
+ return -1;
+
+ }
+
+ if (result < 0 || result >= items.Count)
+ result = focused_item_index;
+
+ return result;
+ }
+
ListViewItem selection_start;
private bool SelectItems (ArrayList sel_items)
bool hover_processed = false;
bool checking = false;
ListViewItem prev_hovered_item;
-#if NET_2_0
ListViewItem prev_tooltip_item;
-#endif
int clicks;
Point drag_begin = new Point (-1, -1);
internal int dragged_item_index = -1;
ArrayList result = new ArrayList ();
for (int i = 0; i < owner.Items.Count; i++) {
bool intersects;
-#if NET_2_0
// Can't iterate over specific items properties in virtualmode
if (owner.View == View.Details && !owner.FullRowSelect && !owner.VirtualMode)
-#else
- if (owner.View == View.Details && !owner.FullRowSelect)
-#endif
intersects = BoxIntersectsText (i);
else
intersects = BoxIntersectsItem (i);
// and if we are in 1.1 profile only take into account
// double clicks
if (owner.StateImageList != null && owner.StateImageList.Images.Count < 2
-#if !NET_2_0
- && me.Clicks == 1
-#endif
)
return;
if (owner.View == View.Details) {
bool over_text = item.TextBounds.Contains (pt);
if (owner.FullRowSelect) {
- clicked_item = owner.items [i];
+ clicked_item = item;
bool over_item_column = (me.X > owner.Columns[0].X && me.X < owner.Columns[0].X + owner.Columns[0].Width);
if (!over_text && over_item_column && owner.MultiSelect)
box_selecting = true;
clicked_item.Selected = true;
}
-#if NET_2_0
if (owner.VirtualMode && changed) {
// Broken event - It's not fired from Item.Selected also
ListViewVirtualItemsSelectionRangeChangedEventArgs args =
owner.OnVirtualItemsSelectionRangeChanged (args);
}
-#endif
// Report clicks only if the item was clicked. On MS the
// clicks are only raised if you click an item
clicks = me.Clicks;
if (owner.LabelEdit && !changed)
BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
}
+
+ drag_begin = me.Location;
+ dragged_item_index = clicked_item.Index;
} else {
if (owner.MultiSelect)
box_selecting = true;
return;
if ((me.Button != MouseButtons.Left && me.Button != MouseButtons.Right) &&
!hover_processed && owner.Activation != ItemActivation.OneClick
-#if NET_2_0
&& !owner.ShowItemToolTips
-#endif
)
return;
// Need to invalidate the item in HotTracking to show/hide the underline style
if (owner.Activation == ItemActivation.OneClick) {
if (item == null && owner.HotItemIndex != -1) {
-#if NET_2_0
if (owner.HotTracking)
Invalidate (owner.Items [owner.HotItemIndex].Bounds); // Previous one
-#endif
Cursor = Cursors.Default;
owner.HotItemIndex = -1;
} else if (item != null && owner.HotItemIndex == -1) {
-#if NET_2_0
if (owner.HotTracking)
Invalidate (item.Bounds);
-#endif
Cursor = Cursors.Hand;
owner.HotItemIndex = item.Index;
}
if (me.Button == MouseButtons.Left || me.Button == MouseButtons.Right) {
- if (drag_begin.X == -1 && drag_begin.Y == -1) {
- if (item != null) {
- drag_begin = new Point (me.X, me.Y);
- dragged_item_index = item.Index;
- }
-
- } else {
+ if (drag_begin != new Point (-1, -1)) {
Rectangle r = new Rectangle (drag_begin, SystemInformation.DragSize);
if (!r.Contains (me.X, me.Y)) {
ListViewItem dragged_item = owner.items [dragged_item_index];
}
}
-#if NET_2_0
if (owner.ShowItemToolTips) {
if (item == null) {
owner.item_tooltip.Active = false;
prev_tooltip_item = item;
}
}
-#endif
}
Select (); // Make sure we have the focus, since MouseHover doesn't give it to us
}
-#if NET_2_0
owner.OnItemMouseHover (new ListViewItemMouseHoverEventArgs (item));
-#endif
}
void HandleClicks (MouseEventArgs me)
// if the click is not on an item,
// clicks remains as 0
if (clicks > 1) {
-#if !NET_2_0
- owner.OnDoubleClick (EventArgs.Empty);
- } else if (clicks == 1) {
- owner.OnClick (EventArgs.Empty);
-#else
owner.OnDoubleClick (EventArgs.Empty);
owner.OnMouseDoubleClick (me);
} else if (clicks == 1) {
owner.OnClick (EventArgs.Empty);
owner.OnMouseClick (me);
-#endif
}
clicks = 0;
case View.List:
Scroll (h_scroll, -ItemSize.Width * lines);
break;
-#if NET_2_0
case View.Tile:
if (!Application.VisualStylesEnabled)
goto case View.LargeIcon;
Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * 2 * lines);
break;
-#endif
}
}
else if (focused_item_index != -1 && focused_item_index < items.Count) // Previous focused item
GetItemAtDisplayIndex (focused_item_index).Focused = false;
focused_item_index = display_index;
-#if NET_2_0
- OnUIAFocusedItemChanged ();
-#endif
+ if (display_index == -1)
+ OnUIAFocusedItemChanged ();
+ // otherwise the event will have been fired
+ // when the ListViewItem's Focused was set
}
private void HorizontalScroller (object sender, EventArgs e)
protected override void CreateHandle ()
{
base.CreateHandle ();
+ is_selection_available = true;
for (int i = 0; i < SelectedItems.Count; i++)
OnSelectedIndexChanged (EventArgs.Empty);
}
protected override void Dispose (bool disposing)
{
if (disposing) {
- h_scroll.Dispose ();
- v_scroll.Dispose ();
-
large_image_list = null;
small_image_list = null;
state_image_list = null;
foreach (ColumnHeader col in columns)
col.SetListView (null);
-#if NET_2_0
if (!virtual_mode) // In virtual mode we don't save the items
-#endif
foreach (ListViewItem item in items)
item.Owner = null;
}
eh (this, e);
}
-#if NET_2_0
protected override void OnBackgroundImageChanged (EventArgs e)
{
item_control.BackgroundImage = BackgroundImage;
base.OnBackgroundImageChanged (e);
}
-#endif
protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
{
eh (this, e);
}
- protected virtual void OnColumnClick (ColumnClickEventArgs e)
+ protected internal virtual void OnColumnClick (ColumnClickEventArgs e)
{
ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]);
if (eh != null)
eh (this, e);
}
-#if NET_2_0
protected internal virtual void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
{
DrawListViewColumnHeaderEventHandler eh = (DrawListViewColumnHeaderEventHandler)(Events[DrawColumnHeaderEvent]);
eh(this, e);
}
-#else
- protected override void OnEnabledChanged (EventArgs e)
- {
- base.OnEnabledChanged (e);
- }
-#endif
-
protected override void OnFontChanged (EventArgs e)
{
base.OnFontChanged (e);
{
base.OnHandleCreated (e);
CalculateListView (alignment);
-#if NET_2_0
if (!virtual_mode) // Sorting is not allowed in virtual mode
-#endif
Sort ();
}
eh (this, ice);
}
-#if NET_2_0
protected internal virtual void OnItemChecked (ItemCheckedEventArgs e)
{
ItemCheckedEventHandler eh = (ItemCheckedEventHandler)(Events [ItemCheckedEvent]);
if (eh != null)
eh (this, e);
}
-#endif
protected virtual void OnItemDrag (ItemDragEventArgs e)
{
eh (this, e);
}
-#if NET_2_0
protected virtual void OnItemMouseHover (ListViewItemMouseHoverEventArgs e)
{
ListViewItemMouseHoverEventHandler eh = (ListViewItemMouseHoverEventHandler)(Events [ItemMouseHoverEvent]);
{
base.OnParentChanged (e);
}
-#endif
protected virtual void OnSelectedIndexChanged (EventArgs e)
{
base.OnSystemColorsChanged (e);
}
-#if NET_2_0
protected internal virtual void OnCacheVirtualItems (CacheVirtualItemsEventArgs e)
{
CacheVirtualItemsEventHandler eh = (CacheVirtualItemsEventHandler)Events [CacheVirtualItemsEvent];
if (eh != null)
eh (this, e);
}
-#endif
protected void RealizeProperties ()
{
Redraw (true);
}
-#if NET_2_0
public void AutoResizeColumn (int columnIndex, ColumnHeaderAutoResizeStyle headerAutoResize)
{
if (columnIndex < 0 || columnIndex >= columns.Count)
col.AutoResize (headerAutoResize);
EndUpdate ();
}
-#endif
public void BeginUpdate ()
{
return;
Rectangle view_rect = item_control.ClientRectangle;
- Rectangle bounds = new Rectangle (GetItemLocation (index), ItemSize);
+ // Avoid direct access to items in virtual mode, and use item bounds otherwise, since we could have reordered items
+ Rectangle bounds = virtual_mode ? new Rectangle (GetItemLocation (index), ItemSize) : items [index].Bounds;
+
+ if (view == View.Details && header_style != ColumnHeaderStyle.None) {
+ view_rect.Y += header_control.Height;
+ view_rect.Height -= header_control.Height;
+ }
if (view_rect.Contains (bounds))
return;
h_scroll.Value += (bounds.Right - view_rect.Right);
}
- if (bounds.Top < 0)
- v_scroll.Value += bounds.Top;
+ if (bounds.Top < view_rect.Y)
+ v_scroll.Value += bounds.Top - view_rect.Y;
else if (bounds.Bottom > view_rect.Bottom)
v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
}
-#if NET_2_0
public ListViewItem FindItemWithText (string text)
{
if (items.Count == 0)
{
return FindItemWithText (text, includeSubItemsInSearch, startIndex, isPrefixSearch, false);
}
-#endif
internal ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch, bool roundtrip)
{
if (text == null)
throw new ArgumentNullException ("text");
-#if NET_2_0
if (virtual_mode) {
SearchForVirtualItemEventArgs args = new SearchForVirtualItemEventArgs (true,
isPrefixSearch, includeSubItemsInSearch, text, Point.Empty,
return null;
}
-#endif
int i = startIndex;
while (true) {
return null;
}
-#if NET_2_0
public ListViewItem FindNearestItem (SearchDirectionHint searchDirection, int x, int y)
{
return FindNearestItem (searchDirection, new Point (x, y));
return item;
}
-#endif
public ListViewItem GetItemAt (int x, int y)
{
return items [index].GetBounds (portion);
}
-#if NET_2_0
public ListViewHitTestInfo HitTest (Point point)
{
return HitTest (point.X, point.Y);
if (!invalidateOnly)
Update ();
}
-#endif
public void Sort ()
{
-#if NET_2_0
if (virtual_mode)
throw new InvalidOperationException ();
-#endif
Sort (true);
}
}
}
-#if NET_2_0
[ListBindable (false)]
-#endif
public class CheckedIndexCollection : IList, ICollection, IEnumerable
{
private readonly ListView owner;
}
} // CheckedIndexCollection
-#if NET_2_0
[ListBindable (false)]
-#endif
public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
{
private readonly ListView owner;
public ListViewItem this [int index] {
get {
-#if NET_2_0
if (owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
ArrayList checked_items = List;
if (index < 0 || index >= checked_items.Count)
throw new ArgumentOutOfRangeException ("index");
}
}
-#if NET_2_0
public virtual ListViewItem this [string key] {
get {
int idx = IndexOfKey (key);
return idx == -1 ? null : (ListViewItem) List [idx];
}
}
-#endif
bool ICollection.IsSynchronized {
get { return false; }
return List.Contains (item);
}
-#if NET_2_0
public virtual bool ContainsKey (string key)
{
return IndexOfKey (key) != -1;
}
-#endif
public void CopyTo (Array dest, int index)
{
-#if NET_2_0
if (owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
if (!owner.CheckBoxes)
return;
List.CopyTo (dest, index);
public IEnumerator GetEnumerator ()
{
-#if NET_2_0
if (owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
if (!owner.CheckBoxes)
return (new ListViewItem [0]).GetEnumerator ();
return List.GetEnumerator ();
public int IndexOf (ListViewItem item)
{
-#if NET_2_0
if (owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
if (!owner.CheckBoxes)
return -1;
return List.IndexOf (item);
}
-#if NET_2_0
public virtual int IndexOfKey (string key)
{
-#if NET_2_0
if (owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
if (key == null || key.Length == 0)
return -1;
return -1;
}
-#endif
#endregion // Public Methods
internal ArrayList List {
}
} // CheckedListViewItemCollection
-#if NET_2_0
[ListBindable (false)]
-#endif
public class ColumnHeaderCollection : IList, ICollection, IEnumerable
{
internal ArrayList list;
private ListView owner;
#region UIA Framework Events
-#if NET_2_0
//NOTE:
// We are using Reflection to add/remove internal events.
// Class ListViewProvider uses the events when View is Details.
eh (owner, args);
}
-#endif
#endregion UIA Framework Events
#region Public Constructor
}
}
-#if NET_2_0
public virtual ColumnHeader this [string key] {
get {
int idx = IndexOfKey (key);
return (ColumnHeader) list [idx];
}
}
-#endif
bool ICollection.IsSynchronized {
get { return true; }
int idx = list.Add (value);
owner.AddColumn (value, idx, true);
-#if NET_2_0
//UIA Framework event: Item Added
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
-#endif
return idx;
}
-#if NET_2_0
public virtual ColumnHeader Add (string text, int width, HorizontalAlignment textAlign)
{
string str = text;
-#else
- public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
- {
-#endif
ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
this.Add (colHeader);
return colHeader;
}
-#if NET_2_0
public virtual ColumnHeader Add (string text)
{
return Add (String.Empty, text);
Add (colHeader);
return colHeader;
}
-#endif
public virtual void AddRange (ColumnHeader [] values)
{
list.Clear ();
owner.ReorderColumns (new int [0], true);
-#if NET_2_0
//UIA Framework event: Items cleared
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
-#endif
}
return list.Contains (value);
}
-#if NET_2_0
public virtual bool ContainsKey (string key)
{
return IndexOfKey (key) != -1;
}
-#endif
public IEnumerator GetEnumerator ()
{
return list.IndexOf (value);
}
-#if NET_2_0
public virtual int IndexOfKey (string key)
{
if (key == null || key.Length == 0)
return -1;
}
-#endif
public void Insert (int index, ColumnHeader value)
{
list.Insert (index, value);
owner.AddColumn (value, index, true);
-#if NET_2_0
//UIA Framework event: Item added
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
-#endif
}
-#if NET_2_0
public void Insert (int index, string text)
{
Insert (index, String.Empty, text);
colHeader.ImageKey = imageKey;
Insert (index, colHeader);
}
-#endif
-#if NET_2_0
public void Insert (int index, string text, int width, HorizontalAlignment textAlign)
{
string str = text;
-#else
- public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
- {
-#endif
ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
this.Insert (index, colHeader);
}
column.InternalDisplayIndex = -1;
owner.ReorderColumns (display_indices, true);
-#if NET_2_0
//UIA Framework event: Item Removed
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, column));
-#endif
}
-#if NET_2_0
public virtual void RemoveByKey (string key)
{
int idx = IndexOfKey (key);
if (idx != -1)
RemoveAt (idx);
}
-#endif
public virtual void RemoveAt (int index)
{
} // ColumnHeaderCollection
-#if NET_2_0
[ListBindable (false)]
-#endif
public class ListViewItemCollection : IList, ICollection, IEnumerable
{
private readonly ArrayList list;
private ListView owner;
-#if NET_2_0
private ListViewGroup group;
-#endif
#region UIA Framework Events
-#if NET_2_0
//NOTE:
// We are using Reflection to add/remove internal events.
// Class ListViewProvider uses the events.
eh (owner, args);
}
-#endif
#endregion UIA Framework Events
// The collection can belong to a ListView (main) or to a ListViewGroup (sub-collection)
}
#endregion // Public Constructor
-#if NET_2_0
internal ListViewItemCollection (ListView owner, ListViewGroup group) : this (owner)
{
this.group = group;
is_main_collection = false;
}
-#endif
#region Public Properties
[Browsable (false)]
public int Count {
get {
-#if NET_2_0
if (owner != null && owner.VirtualMode)
return owner.VirtualListSize;
-#endif
return list.Count;
}
get { return false; }
}
-#if NET_2_0
public virtual ListViewItem this [int index] {
-#else
- public virtual ListViewItem this [int displayIndex] {
-#endif
get {
-#if !NET_2_0
- int index = displayIndex;
-#endif
-
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException ("index");
-#if NET_2_0
if (owner != null && owner.VirtualMode)
return RetrieveVirtualItemFromOwner (index);
-#endif
return (ListViewItem) list [index];
}
set {
-#if !NET_2_0
- int index = displayIndex;
-#endif
-
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException ("index");
-#if NET_2_0
if (owner != null && owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
if (list.Contains (value))
throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
if (is_main_collection)
value.Owner = owner;
-#if NET_2_0
else {
if (value.Group != null)
value.Group.Items.Remove (value);
value.SetGroup (group);
}
-#endif
-#if NET_2_0
//UIA Framework event: Item Replaced
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, list [index]));
-#endif
list [index] = value;
CollectionChanged (true);
-#if NET_2_0
//UIA Framework event: Item Replaced
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
-#endif
}
}
-#if NET_2_0
public virtual ListViewItem this [string key] {
get {
int idx = IndexOfKey (key);
return this [idx];
}
}
-#endif
bool ICollection.IsSynchronized {
get { return true; }
object IList.this [int index] {
get { return this [index]; }
set {
-#if NET_2_0
//UIA Framework event: Item Replaced
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, this [index]));
-#endif
if (value is ListViewItem)
this [index] = (ListViewItem) value;
this [index] = new ListViewItem (value.ToString ());
OnChange ();
-#if NET_2_0
//UIA Framework event: Item Replaced
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
-#endif
}
}
#endregion // Public Properties
#region Public Methods
public virtual ListViewItem Add (ListViewItem value)
{
-#if NET_2_0
if (owner != null && owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
AddItem (value);
if (is_main_collection || value.ListView != null)
CollectionChanged (true);
-#if NET_2_0
//UIA Framework event: Item Added
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
-#endif
return value;
}
return this.Add (item);
}
-#if NET_2_0
public virtual ListViewItem Add (string text, string imageKey)
{
ListViewItem item = new ListViewItem (text, imageKey);
item.Name = key;
return this.Add (item);
}
-#endif
-#if NET_2_0
public void AddRange (ListViewItem [] items)
{
-#else
- public void AddRange (ListViewItem [] values)
- {
- ListViewItem [] items = values;
-#endif
if (items == null)
throw new ArgumentNullException ("Argument cannot be null!", "items");
-#if NET_2_0
if (owner != null && owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
owner.BeginUpdate ();
foreach (ListViewItem item in items) {
AddItem (item);
-#if NET_2_0
//UIA Framework event: Item Added
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
-#endif
}
owner.EndUpdate ();
CollectionChanged (true);
}
-#if NET_2_0
public void AddRange (ListViewItemCollection items)
{
if (items == null)
items.CopyTo (itemArray,0);
this.AddRange (itemArray);
}
-#endif
public virtual void Clear ()
{
-#if NET_2_0
if (owner != null && owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
if (is_main_collection && owner != null) {
owner.SetFocusedItem (-1);
owner.h_scroll.Value = owner.v_scroll.Value = 0;
-
+
+ // first remove any item in the groups that *are* part of this LV too
+ foreach (ListViewGroup group in owner.groups)
+ group.Items.ClearItemsWithSameListView ();
+
foreach (ListViewItem item in list) {
owner.item_control.CancelEdit (item);
item.Owner = null;
}
-
}
-#if NET_2_0
else
foreach (ListViewItem item in list)
item.SetGroup (null);
-#endif
list.Clear ();
CollectionChanged (false);
-#if NET_2_0
//UIA Framework event: Items Removed
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
-#endif
}
+ // This method is intended to be used from ListViewGroup.Items, not from ListView.Items,
+ // added for performance reasons (avoid calling manually Remove for every item on ListViewGroup.Items)
+ void ClearItemsWithSameListView ()
+ {
+ if (is_main_collection)
+ return;
+
+ int counter = list.Count - 1;
+ while (counter >= 0) {
+ ListViewItem item = list [counter] as ListViewItem;
+
+ // remove only if the items in group have being added to the ListView too
+ if (item.ListView == group.ListView) {
+ list.RemoveAt (counter);
+ item.SetGroup (null);
+ }
+
+ counter--;
+ }
+ }
+
public bool Contains (ListViewItem item)
{
return IndexOf (item) != -1;
}
-#if NET_2_0
public virtual bool ContainsKey (string key)
{
return IndexOfKey (key) != -1;
}
-#endif
public void CopyTo (Array dest, int index)
{
list.CopyTo (dest, index);
}
-#if NET_2_0
public ListViewItem [] Find (string key, bool searchAllSubItems)
{
if (key == null)
return retval;
}
-#endif
public IEnumerator GetEnumerator ()
{
-#if NET_2_0
if (owner != null && owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
// This enumerator makes a copy of the collection so
// it can be deleted from in a foreach
int result;
ListViewItem li;
-#if NET_2_0
if (owner != null && owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
if (item is ListViewItem) {
li = (ListViewItem) item;
result = list.Add (li);
CollectionChanged (true);
-#if NET_2_0
//UIA Framework event: Item Added
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, li));
-#endif
return result;
}
else
this.Insert (index, item.ToString ());
-#if NET_2_0
//UIA Framework event: Item Added
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, this [index]));
-#endif
}
void IList.Remove (object item)
public int IndexOf (ListViewItem item)
{
-#if NET_2_0
if (owner != null && owner.VirtualMode) {
for (int i = 0; i < Count; i++)
if (RetrieveVirtualItemFromOwner (i) == item)
return -1;
}
-#endif
return list.IndexOf (item);
}
-#if NET_2_0
public virtual int IndexOfKey (string key)
{
if (key == null || key.Length == 0)
return -1;
}
-#endif
public ListViewItem Insert (int index, ListViewItem item)
{
if (index < 0 || index > list.Count)
throw new ArgumentOutOfRangeException ("index");
-#if NET_2_0
if (owner != null && owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
if (list.Contains (item))
throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
if (is_main_collection)
item.Owner = owner;
-#if NET_2_0
else {
if (item.Group != null)
item.Group.Items.Remove (item);
item.SetGroup (group);
}
-#endif
list.Insert (index, item);
if (is_main_collection || item.ListView != null)
CollectionChanged (true);
-#if NET_2_0
+ // force an update of the selected info if the new item is selected.
+ if (item.Selected)
+ item.SetSelectedCore (true);
//UIA Framework event: Item Added
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
-#endif
return item;
}
return this.Insert (index, new ListViewItem (text, imageIndex));
}
-#if NET_2_0
public ListViewItem Insert (int index, string text, string imageKey)
{
ListViewItem lvi = new ListViewItem (text, imageKey);
lvi.Name = key;
return Insert (index, lvi);
}
-#endif
public virtual void Remove (ListViewItem item)
{
-#if NET_2_0
if (owner != null && owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
int idx = list.IndexOf (item);
if (idx != -1)
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException ("index");
-#if NET_2_0
if (owner != null && owner.VirtualMode)
throw new InvalidOperationException ();
-#endif
ListViewItem item = (ListViewItem) list [index];
list.RemoveAt (index);
-#if NET_2_0
if (is_main_collection) {
item.Owner = null;
if (item.Group != null)
item.Group.Items.Remove (item);
} else
item.SetGroup (null);
-#else
- item.Owner = null;
-#endif
CollectionChanged (false);
if (selection_changed && owner != null)
owner.OnSelectedIndexChanged (EventArgs.Empty);
-#if NET_2_0
//UIA Framework event: Item Removed
OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, item));
-#endif
}
-#if NET_2_0
public virtual void RemoveByKey (string key)
{
int idx = IndexOfKey (key);
if (idx != -1)
RemoveAt (idx);
}
-#endif
#endregion // Public Methods
}
}
-#if NET_2_0
internal ListViewGroup Group {
get {
return group;
group = value;
}
}
-#endif
void AddItem (ListViewItem value)
{
throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value");
if (is_main_collection)
value.Owner = owner;
-#if NET_2_0
else {
if (value.Group != null)
value.Group.Items.Remove (value);
value.SetGroup (group);
}
-#endif
list.Add (value);
+ // force an update of the selected info if the new item is selected.
+ if (value.Selected)
+ value.SetSelectedCore (true);
}
void CollectionChanged (bool sort)
}
}
-#if NET_2_0
ListViewItem RetrieveVirtualItemFromOwner (int displayIndex)
{
RetrieveVirtualItemEventArgs args = new RetrieveVirtualItemEventArgs (displayIndex);
ListViewItem retval = args.Item;
retval.Owner = owner;
retval.DisplayIndex = displayIndex;
+ retval.Layout ();
return retval;
}
-#endif
internal event CollectionChangedHandler Changed;
//
// In virtual mode, SelectedIndexCollection directly saves the selection
// information, instead of getting it from Items, making List read-and-write
-#if NET_2_0
[ListBindable (false)]
-#endif
public class SelectedIndexCollection : IList, ICollection, IEnumerable
{
private readonly ListView owner;
[Browsable (false)]
public int Count {
get {
- if (!owner.IsHandleCreated)
+ if (!owner.is_selection_available)
return 0;
return List.Count;
public bool IsReadOnly {
get {
-#if NET_2_0
return false;
-#else
- return true;
-#endif
}
}
public int this [int index] {
get {
- if (!owner.IsHandleCreated || index < 0 || index >= List.Count)
+ if (!owner.is_selection_available || index < 0 || index >= List.Count)
throw new ArgumentOutOfRangeException ("index");
return (int) List [index];
bool IList.IsFixedSize {
get {
-#if NET_2_0
return false;
-#else
- return true;
-#endif
}
}
#endregion // Public Properties
#region Public Methods
-#if NET_2_0
public int Add (int itemIndex)
{
if (itemIndex < 0 || itemIndex >= owner.Items.Count)
throw new ArgumentOutOfRangeException ("index");
- if (owner.virtual_mode && !owner.IsHandleCreated)
+ if (owner.virtual_mode && !owner.is_selection_available)
return -1;
owner.Items [itemIndex].Selected = true;
- if (!owner.IsHandleCreated)
+ if (!owner.is_selection_available)
return 0;
return List.Count;
}
-#endif
-#if NET_2_0
- public
-#else
- internal
-#endif
- void Clear ()
+ public void Clear ()
{
- if (!owner.IsHandleCreated)
+ if (!owner.is_selection_available)
return;
int [] indexes = (int []) List.ToArray (typeof (int));
public int IndexOf (int selectedIndex)
{
- if (!owner.IsHandleCreated)
+ if (!owner.is_selection_available)
return -1;
return List.IndexOf (selectedIndex);
}
-#if NET_2_0
public void Remove (int itemIndex)
{
if (itemIndex < 0 || itemIndex >= owner.Items.Count)
owner.Items [itemIndex].Selected = false;
}
-#endif
#endregion // Public Methods
internal ArrayList List {
get {
if (list == null) {
list = new ArrayList ();
-#if NET_2_0
if (!owner.VirtualMode)
-#endif
for (int i = 0; i < owner.Items.Count; i++) {
if (owner.Items [i].Selected)
list.Add (i);
Reset ();
}
-#if NET_2_0
internal void RemoveIndex (int index)
{
int idx = List.BinarySearch (index);
List.Insert (iMin, index);
}
-#endif
} // SelectedIndexCollection
-#if NET_2_0
[ListBindable (false)]
-#endif
public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
{
private readonly ListView owner;
public ListViewItem this [int index] {
get {
- if (!owner.IsHandleCreated || index < 0 || index >= Count)
+ if (!owner.is_selection_available || index < 0 || index >= Count)
throw new ArgumentOutOfRangeException ("index");
int item_index = owner.SelectedIndices [index];
}
}
-#if NET_2_0
public virtual ListViewItem this [string key] {
get {
int idx = IndexOfKey (key);
return this [idx];
}
}
-#endif
bool ICollection.IsSynchronized {
get { return false; }
return IndexOf (item) != -1;
}
-#if NET_2_0
public virtual bool ContainsKey (string key)
{
return IndexOfKey (key) != -1;
}
-#endif
public void CopyTo (Array dest, int index)
{
- if (!owner.IsHandleCreated)
+ if (!owner.is_selection_available)
return;
if (index > Count) // Throws ArgumentException instead of IOOR exception
throw new ArgumentException ("index");
public IEnumerator GetEnumerator ()
{
- if (!owner.IsHandleCreated)
+ if (!owner.is_selection_available)
return (new ListViewItem [0]).GetEnumerator ();
ListViewItem [] items = new ListViewItem [Count];
public int IndexOf (ListViewItem item)
{
- if (!owner.IsHandleCreated)
+ if (!owner.is_selection_available)
return -1;
for (int i = 0; i < Count; i++)
return -1;
}
-#if NET_2_0
public virtual int IndexOfKey (string key)
{
- if (!owner.IsHandleCreated || key == null || key.Length == 0)
+ if (!owner.is_selection_available || key == null || key.Length == 0)
return -1;
for (int i = 0; i < Count; i++) {
return -1;
}
-#endif
#endregion // Public Methods
} // SelectedListViewItemCollection
}
#endregion // Subclasses
-#if NET_2_0
protected override void OnResize (EventArgs e)
{
base.OnResize (e);
cwceh (this, changing);
return !changing.Cancel;
}
-#else
- //
- // 1.0 profile based implementation
- //
- bool CanProceedWithResize (ColumnHeader col, int width)
- {
- return true;
- }
- void RaiseColumnWidthChanged (int resize_column)
+ internal void RaiseColumnWidthChanged (ColumnHeader column)
{
+ int index = Columns.IndexOf (column);
+ RaiseColumnWidthChanged (index);
}
-#endif
-#if NET_2_0
#region UIA Framework: Methods, Properties and Events
return group.HeaderBounds;
}
+ internal int UIAItemsLocationLength
+ {
+ get { return items_location.Length; }
+ }
+
private void OnUIACheckBoxesChanged ()
{
EventHandler eh = (EventHandler) Events [UIACheckBoxesChangedEvent];
eh (this, EventArgs.Empty);
}
- private void OnUIAFocusedItemChanged ()
+ internal void OnUIAFocusedItemChanged ()
{
EventHandler eh = (EventHandler) Events [UIAFocusedItemChangedEvent];
if (eh != null)
#endregion // UIA Framework: Methods, Properties and Events
-#endif
}
}