/// <summary> /// Create a OlvListViewHitTestInfo when the header was hit /// </summary> public OlvListViewHitTestInfo(AdvancedListView olv, int iColumn, bool isOverCheckBox, int iDivider) { this.ListView = olv; this.ColumnIndex = iColumn; this.HeaderDividerIndex = iDivider; this.HitTestLocation = isOverCheckBox ? HitTestLocation.HeaderCheckBox : (iDivider < 0 ? HitTestLocation.Header : HitTestLocation.HeaderDivider); }
/// <summary> /// Create a text filter that includes rows where any cell begins with one of the given strings /// </summary> /// <param name="olv"></param> /// <param name="texts"></param> /// <returns></returns> public static TextMatchFilter Prefix(AdvancedListView olv, params string[] texts) { var filter = new TextMatchFilter(olv); filter.PrefixStrings = texts; return(filter); }
/// <summary> /// Create a text filter that includes rows where any cell contains any of the given strings. /// </summary> /// <param name="olv"></param> /// <param name="texts"></param> /// <returns></returns> public static TextMatchFilter Contains(AdvancedListView olv, params string[] texts) { var filter = new TextMatchFilter(olv); filter.ContainsStrings = texts; return(filter); }
/// <summary> /// Draw a tint over everything in the FluentListView except the /// row under the mouse. /// </summary> /// <param name="olv"></param> /// <param name="g"></param> /// <param name="r"></param> public override void Draw(AdvancedListView olv, Graphics g, Rectangle r) { if (!r.Contains(olv.PointToClient(Cursor.Position))) { return; } Rectangle bounds = this.RowBounds; if (bounds.IsEmpty) { if (olv.View == View.Tile) { g.FillRectangle(this.FillBrush, r); } return; } using (Region newClip = new Region(r)) { bounds.Inflate(this.BoundsPadding); newClip.Exclude(this.GetRoundedRect(bounds, this.CornerRounding)); Region originalClip = g.Clip; g.Clip = newClip; g.FillRectangle(this.FillBrush, r); g.Clip = originalClip; } }
/// <summary> /// Create a text filter that will include rows where any cell matches /// any of the given regex expressions. /// </summary> /// <param name="olv"></param> /// <param name="texts"></param> /// <returns></returns> /// <remarks>Any string that is not a valid regex expression will be ignored.</remarks> public static TextMatchFilter Regex(AdvancedListView olv, params string[] texts) { TextMatchFilter filter = new TextMatchFilter(olv); filter.RegexStrings = texts; return(filter); }
/// <summary> /// Handle a user-generated ItemCheck event /// </summary> /// <param name="sender"></param> /// <param name="e"></param> virtual protected void HandleItemChecked(object sender, ItemCheckEventArgs e) { ToolStripCheckedListBox checkedList = sender as ToolStripCheckedListBox; if (checkedList == null) { return; } OLVColumn column = checkedList.Tag as OLVColumn; if (column == null) { return; } AdvancedListView listView = column.ListView as AdvancedListView; if (listView == null) { return; } // Deal with the "Select All" item if there is one int selectAllIndex = checkedList.Items.IndexOf(SELECT_ALL_LABEL); if (selectAllIndex >= 0) { HandleSelectAllItem(e, checkedList, selectAllIndex); } }
/// <summary> /// Create a Filter menu on the given tool tip for the given column in the given FluentListView. /// </summary> /// <remarks>This is the main entry point into this class.</remarks> /// <param name="strip"></param> /// <param name="listView"></param> /// <param name="column"></param> /// <returns>The strip that should be shown to the user</returns> virtual public ToolStripDropDown MakeFilterMenu(ToolStripDropDown strip, AdvancedListView listView, OLVColumn column) { if (strip == null) { throw new ArgumentNullException("strip"); } if (listView == null) { throw new ArgumentNullException("listView"); } if (column == null) { throw new ArgumentNullException("column"); } if (!column.UseFiltering || column.ClusteringStrategy == null || listView.Objects == null) { return(strip); } List <ICluster> clusters = this.Cluster(column.ClusteringStrategy, listView, column); if (clusters.Count > 0) { this.SortClusters(column.ClusteringStrategy, clusters); strip.Items.Add(this.CreateFilteringMenuItem(column, clusters)); } return(strip); }
/// <summary> /// Edit a given value /// </summary> /// <param name="context"></param> /// <param name="provider"></param> /// <param name="value"></param> /// <returns></returns> public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { if (context == null) { throw new ArgumentNullException("context"); } if (provider == null) { throw new ArgumentNullException("provider"); } // Figure out which FluentListView we are working on. This should be the Instance of the context. AdvancedListView olv = context.Instance as AdvancedListView; Debug.Assert(olv != null, "Instance must be an FluentListView"); // Edit all the columns, not just the ones that are visible base.EditValue(context, provider, olv.AllColumns); // Set the columns on the ListView to just the visible columns List <OLVColumn> newColumns = olv.GetFilteredColumns(View.Details); olv.Columns.Clear(); olv.Columns.AddRange(newColumns.ToArray()); return(olv.Columns); }
/// <summary> /// Somewhere the parent of the bound OLV has changed. Update /// our events. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void objectListView_ParentChanged(object sender, EventArgs e) { AdvancedListView olv = this.objectListView; IOverlay overlay = this.Overlay; this.Unbind(); this.Bind(olv, overlay); }
/// <summary> /// Create a data object which operates on the given model objects /// in the given FluentListView /// </summary> /// <param name="olv">The source of the data object</param> /// <param name="modelObjects">The model objects to be put into the data object</param> public OLVDataObject(AdvancedListView olv, IList modelObjects) { objectListView = olv; this.modelObjects = modelObjects; includeHiddenColumns = olv.IncludeHiddenColumnsInDataTransfer; includeColumnHeaders = olv.IncludeColumnHeadersInCopy; CreateTextFormats(); }
/// <summary> /// /// </summary> /// <param name="collection"></param> public override void SetObjects(IEnumerable collection) { ArrayList newObjects = AdvancedListView.EnumerableToArray(collection, true); this.fullObjectList = newObjects; this.FilterObjects(); this.RebuildIndexMap(); }
/// <summary> /// Draw a filled border /// </summary> /// <param name="olv"></param> /// <param name="g"></param> /// <param name="r"></param> public override void Draw(AdvancedListView olv, Graphics g, Rectangle r) { Rectangle bounds = this.CalculateBounds(); if (!bounds.IsEmpty) { this.DrawFilledBorder(g, bounds); } }
/// <summary> /// Draw this overlay /// </summary> /// <param name="olv">The FluentListView being decorated</param> /// <param name="g">The Graphics used for drawing</param> /// <param name="r">The bounds of the rendering</param> public virtual void Draw(AdvancedListView olv, Graphics g, Rectangle r) { Rectangle insetRect = r; insetRect.Inflate(-this.InsetX, -this.InsetY); // We hard code a transparency of 255 here since transparency is handled by the glass panel this.DrawImage(g, insetRect, this.Image, 255); }
/// <summary> /// Make a DataSourceAdapter /// </summary> public DataSourceAdapter(AdvancedListView olv) { if (olv == null) { throw new ArgumentNullException("olv"); } ListView = olv; // ReSharper disable once DoNotCallOverridableMethodsInConstructor BindListView(ListView); }
/// <summary> /// Create a DataObject when the user does a left mouse drag operation. /// See IDragSource for further information. /// </summary> /// <param name="olv"></param> /// <param name="button"></param> /// <param name="item"></param> /// <returns></returns> public virtual Object StartDrag(AdvancedListView olv, MouseButtons button, OLVListItem item) { // We only drag on left mouse if (button != MouseButtons.Left) { return(null); } return(this.CreateDataObject(olv)); }
/// <summary> /// Generate columns into the given FluentListView that come from the given /// model object type. /// </summary> /// <param name="olv">The FluentListView to modify</param> /// <param name="type">The model type whose attributes will be considered.</param> /// <param name="allProperties">Will columns be generated for properties that are not marked with [OLVColumn].</param> public virtual void GenerateAndReplaceColumns(AdvancedListView olv, Type type, bool allProperties) { IList <OLVColumn> columns = this.GenerateColumns(type, allProperties); TreeListView tlv = olv as TreeListView; if (tlv != null) { this.TryGenerateChildrenDelegates(tlv, type); } this.ReplaceColumns(olv, columns); }
/// <summary> /// Clear all the filters that are applied to the given column /// </summary> /// <param name="column">The column from which filters are to be removed</param> virtual protected void ClearAllFilters(OLVColumn column) { AdvancedListView olv = column.ListView as AdvancedListView; if (olv == null || olv.IsDisposed) { return; } olv.ResetColumnFiltering(); }
/// <summary> /// /// </summary> /// <param name="olv"></param> protected virtual void UnbindListView(AdvancedListView olv) { if (olv == null) { return; } olv.Freezing -= new EventHandler <FreezeEventArgs>(HandleListViewFreezing); olv.SelectionChanged -= new EventHandler(HandleListViewSelectionChanged); olv.BindingContextChanged -= new EventHandler(HandleListViewBindingContextChanged); }
/// <summary> /// Post process columns after creating them and adding them to the AllColumns collection. /// </summary> /// <param name="olv"></param> public virtual void PostCreateColumns(AdvancedListView olv) { if (olv.AllColumns.Exists(delegate(OLVColumn x) { return(x.CheckBoxes); })) { olv.UseSubItemCheckBoxes = true; } if (olv.AllColumns.Exists(delegate(OLVColumn x) { return(x.Index > 0 && (x.ImageGetter != null || !String.IsNullOrEmpty(x.ImageAspectName))); })) { olv.ShowImagesOnSubItems = true; } olv.RebuildColumns(); olv.AutoSizeColumns(); }
/// <summary> /// Open this form so it will edit the columns that are available in the given listview /// when the listview is showing the given type of view. /// </summary> /// <param name="olv">The FluentListView whose columns are to be altered</param> /// <param name="view">The view that is to be altered. Must be View.Details or View.Tile</param> public void OpenOn(AdvancedListView olv, View view) { if (view != View.Details && view != View.Tile) { return; } InitializeForm(olv, view); if (ShowDialog() == DialogResult.OK) { Apply(olv, view); } }
/// <summary> /// Draw this overlay /// </summary> /// <param name="olv">The FluentListView being decorated</param> /// <param name="g">The Graphics used for drawing</param> /// <param name="r">The bounds of the rendering</param> public virtual void Draw(AdvancedListView olv, Graphics g, Rectangle r) { if (String.IsNullOrEmpty(this.Text)) { return; } Rectangle insetRect = r; insetRect.Inflate(-this.InsetX, -this.InsetY); // We hard code a transparency of 255 here since transparency is handled by the glass panel this.DrawText(g, insetRect, this.Text, 255); }
/// <summary> /// The user has pressed OK. Do what's requied. /// </summary> /// <param name="olv"></param> /// <param name="view"></param> protected void Apply(AdvancedListView olv, View view) { olv.Freeze(); // Update the column definitions to reflect whether they have been hidden if (view == View.Details) { foreach (var col in olv.AllColumns) { col.IsVisible = MapColumnToVisible[col]; } } else { foreach (var col in olv.AllColumns) { col.IsTileViewColumn = MapColumnToVisible[col]; } } // Collect the columns are still visible var visibleColumns = RearrangableColumns.FindAll( delegate(OLVColumn x) { return(MapColumnToVisible[x]); }); // Detail view and Tile view have to be handled in different ways. if (view == View.Details) { // Of the still visible columns, change DisplayIndex to reflect their position in the rearranged list olv.ChangeToFilteredColumns(view); foreach (var col in visibleColumns) { col.DisplayIndex = visibleColumns.IndexOf((OLVColumn)col); col.LastDisplayIndex = col.DisplayIndex; } } else { // In Tile view, DisplayOrder does nothing. So to change the display order, we have to change the // order of the columns in the Columns property. // Remember, the primary column is special and has to remain first! var primaryColumn = AllColumns[0]; visibleColumns.Remove(primaryColumn); olv.Columns.Clear(); olv.Columns.Add(primaryColumn); olv.Columns.AddRange(visibleColumns.ToArray()); olv.CalculateReasonableTileSize(); } olv.Unfreeze(); }
/// <summary> /// Replace all the columns in the given listview with the given list of columns. /// </summary> /// <param name="olv"></param> /// <param name="columns"></param> protected virtual void ReplaceColumns(AdvancedListView olv, IList <OLVColumn> columns) { olv.Reset(); // Are there new columns to add? if (columns == null || columns.Count == 0) { return; } // Setup the columns olv.AllColumns.AddRange(columns); this.PostCreateColumns(olv); }
/// <summary> /// Create an exporter that will export all the given rows from the given FluentListView /// </summary> /// <param name="olv"></param> /// <param name="objectsToExport"></param> public OLVExporter(AdvancedListView olv, IEnumerable objectsToExport) { if (olv == null) { throw new ArgumentNullException("olv"); } if (objectsToExport == null) { throw new ArgumentNullException("objectsToExport"); } this.ListView = olv; this.ModelObjects = AdvancedListView.EnumerableToArray(objectsToExport, true); }
/// <summary> /// Replace all columns of the given FluentListView with columns generated /// from the first member of the given enumerable. If the enumerable is /// empty or null, the FluentListView will be cleared. /// </summary> /// <param name="olv">The FluentListView to modify</param> /// <param name="enumerable">The collection whose first element will be used to generate columns.</param> /// <param name="allProperties">Will columns be generated for properties that are not marked with [OLVColumn].</param> static public void GenerateColumns(AdvancedListView olv, IEnumerable enumerable, bool allProperties) { // Generate columns based on the type of the first model in the collection and then quit if (enumerable != null) { foreach (object model in enumerable) { Generator.Instance.GenerateAndReplaceColumns(olv, model.GetType(), allProperties); return; } } // If we reach here, the collection was empty, so we clear the list Generator.Instance.GenerateAndReplaceColumns(olv, null, allProperties); }
/// <summary> /// Create a GroupingParameters /// </summary> /// <param name="olv"></param> /// <param name="groupByColumn"></param> /// <param name="groupByOrder"></param> /// <param name="column"></param> /// <param name="order"></param> /// <param name="secondaryColumn"></param> /// <param name="secondaryOrder"></param> /// <param name="titleFormat"></param> /// <param name="titleSingularFormat"></param> /// <param name="sortItemsByPrimaryColumn"></param> public GroupingParameters(AdvancedListView olv, OLVColumn groupByColumn, SortOrder groupByOrder, OLVColumn column, SortOrder order, OLVColumn secondaryColumn, SortOrder secondaryOrder, string titleFormat, string titleSingularFormat, bool sortItemsByPrimaryColumn) { this.ListView = olv; this.GroupByColumn = groupByColumn; this.GroupByOrder = groupByOrder; this.PrimarySort = column; this.PrimarySortOrder = order; this.SecondarySort = secondaryColumn; this.SecondarySortOrder = secondaryOrder; this.SortItemsByPrimaryColumn = sortItemsByPrimaryColumn; this.TitleFormat = titleFormat; this.TitleSingularFormat = titleSingularFormat; }
/// <summary> /// Handle a key press /// </summary> /// <param name="olv"></param> /// <param name="keyData"></param> /// <returns>True if the key was completely handled.</returns> public virtual bool HandleKey(AdvancedListView olv, Keys keyData) { if (olv == null) { throw new ArgumentNullException("olv"); } CellEditCharacterBehaviour behaviour; if (!CellEditKeyMap.TryGetValue(keyData, out behaviour)) { return(false); } ListView = olv; switch (behaviour) { case CellEditCharacterBehaviour.Ignore: break; case CellEditCharacterBehaviour.CancelEdit: HandleCancelEdit(); break; case CellEditCharacterBehaviour.EndEdit: HandleEndEdit(); break; case CellEditCharacterBehaviour.ChangeColumnLeft: case CellEditCharacterBehaviour.ChangeColumnRight: HandleColumnChange(keyData, behaviour); break; case CellEditCharacterBehaviour.ChangeRowDown: case CellEditCharacterBehaviour.ChangeRowUp: HandleRowChange(keyData, behaviour); break; default: return(HandleCustomVerb(keyData, behaviour)); } ; return(true); }
/// <summary> /// Return the last N subset of the model objects /// </summary> /// <param name="modelObjects"></param> /// <returns></returns> public override IEnumerable Filter(IEnumerable modelObjects) { if (this.Count <= 0) { return(modelObjects); } ArrayList list = AdvancedListView.EnumerableToArray(modelObjects, false); if (this.Count > list.Count) { return(list); } object[] tail = new object[this.Count]; list.CopyTo(list.Count - this.Count, tail, 0, this.Count); return(new ArrayList(tail)); }
/// <summary> /// Create an AutoCompleteCellEditor /// </summary> /// <param name="lv"></param> /// <param name="column"></param> public AutoCompleteCellEditor(AdvancedListView lv, OLVColumn column) { DropDownStyle = ComboBoxStyle.DropDown; var alreadySeen = new Dictionary <string, bool>(); for (var i = 0; i < Math.Min(lv.GetItemCount(), 1000); i++) { var str = column.GetStringValue(lv.GetModelObject(i)); if (!alreadySeen.ContainsKey(str)) { Items.Add(str); alreadySeen[str] = true; } } Sorted = true; AutoCompleteSource = AutoCompleteSource.ListItems; AutoCompleteMode = AutoCompleteMode.Append; }
/// <summary> /// Draw a slight colouring over our tinted column /// </summary> /// <remarks> /// This overlay only works when: /// - the list is in Details view /// - there is at least one row /// - there is a selected column (or a specified tint column) /// </remarks> /// <param name="olv"></param> /// <param name="g"></param> /// <param name="r"></param> public override void Draw(AdvancedListView olv, Graphics g, Rectangle r) { if (olv.View != System.Windows.Forms.View.Details) { return; } if (olv.GetItemCount() == 0) { return; } OLVColumn column = this.ColumnToTint ?? olv.SelectedColumn; if (column == null) { return; } Point sides = NativeMethods.GetScrolledColumnSides(olv, column.Index); if (sides.X == -1) { return; } Rectangle columnBounds = new Rectangle(sides.X, r.Top, sides.Y - sides.X, r.Bottom); // Find the bottom of the last item. The tinting should extend only to there. OLVListItem lastItem = olv.GetLastItemInDisplayOrder(); if (lastItem != null) { Rectangle lastItemBounds = lastItem.Bounds; if (!lastItemBounds.IsEmpty && lastItemBounds.Bottom < columnBounds.Bottom) { columnBounds.Height = lastItemBounds.Bottom - columnBounds.Top; } } g.FillRectangle(this.tintBrush, columnBounds); }