/// <summary> /// Modifies <see cref="ListView.Groups"/> collection to match supplied one. /// </summary> /// <remarks> /// The order of newly inserted groups is preserved. /// The mutual order of already existing groups is left intact to keep algorithm simpler and non-destructive. /// </remarks> public void SetGroups(IReadOnlyList <ListViewGroup> groups, StringComparer nameComparer) { var groupNames = new HashSet <string>(groups.Select(g => g.Name), nameComparer); BeginGroupInsertion(); try { var toRemove = GetGroups().Where(grp => !groupNames.Contains(grp.Name)).ToArray(); foreach (var grp in toRemove) { Groups.Remove(grp); } var existingGroups = GetGroups().ToArray(); // leave only names to be inserted groupNames.ExceptWith(existingGroups.Select(g => g.Name)); for (int i = 0; i < groups.Count; i++) { if (groupNames.Contains(groups[i].Name)) { Groups.Insert(i + _minGroupInsertionIndex, groups[i]); } } } finally { EndGroupInsertion(); } IEnumerable <ListViewGroup> GetGroups() => Groups.Cast <ListViewGroup>().Skip(_minGroupInsertionIndex); }
public void RefreshGroupsHeader() { foreach (var g in Groups.Cast <ListViewGroup>()) { g.Header = $"{g.Name} ({g.Items.Count})"; } }
internal void UpdateGroups() { IMergeRequestCache mergeRequestCache = _dataCache?.MergeRequestCache; if (mergeRequestCache == null) { return; } BeginUpdate(); // Add missing project groups IEnumerable <ProjectKey> allProjects = mergeRequestCache.GetProjects(); foreach (ProjectKey projectKey in allProjects) { if (!Groups.Cast <ListViewGroup>().Any(x => projectKey.Equals((ProjectKey)(x.Tag)))) { CreateGroupForProject(projectKey, true); } } // Remove deleted project groups for (int index = Groups.Count - 1; index >= 0; --index) { ListViewGroup group = Groups[index]; if (!allProjects.Any(x => x.Equals((ProjectKey)group.Tag))) { Groups.Remove(group); } } EndUpdate(); }
public ListViewGroup GroupHitTest(int x, int y) { if (View == View.Details || !ClientRectangle.Contains(x, y)) { return(null); } // TODO: Surely this needs to be marshalled? // Pinning using GCHandle does not work // This code was taken from the dot net implementation of ListView so I guess it must be right var lParam = new LVHITTESTINFO { pt_x = x, pt_y = y }; var index = SendMessage(new HandleRef(this, Handle), 4114, -1, lParam); return((LVHTFlags)lParam.flags == LVHTFlags.LVHT_EX_GROUP_BACKGROUND ? Groups.Cast <ListViewGroup>().SingleOrDefault(g => index == GetGroupId(g)) : null); }
/// <summary> Creates list view items and groups for the given data <paramref name="elements"/>. </summary> /// <param name="elements">Data element collection</param> private void CreateGroupsAndItems(object[] elements) { Items.Clear(); // Groups.Clear(); for (int i = -1; ++i != elements.Length;) { object element = elements[i]; bool hasChildren = ContentProvider.HasChildren(element); if (hasChildren) { object[] children = ContentProvider.GetChildren(element); // Don't create empty groups if (children == null || children.Length == 0) { continue; } // Try to re-use existing groups ListViewGroup group = Groups.Cast <ListViewGroup>().FirstOrDefault(grp => Equals(grp.Tag, element)); if (group == null) { group = new ListViewGroup { Tag = element }; Groups.Add(group); } for (int j = -1; ++j != children.Length;) { CreateListViewItem(children[j], group); } } else { CreateListViewItem(element, null); } } }
private void LayoutItems() { // Lay out each group StackLayoutEngine.HorizontalExpand.Layout(Bounds, Groups.Cast <ILayoutable> ()); }
private IEnumerable <FullMergeRequestKey> getMatchingFilterMergeRequests() { return(Groups .Cast <ListViewGroup>() .SelectMany(group => getMatchingFilterProjectItems(getGroupProjectKey(group)))); }
internal void UpdateItems() { IMergeRequestCache mergeRequestCache = _dataCache?.MergeRequestCache; if (mergeRequestCache == null) { return; } IEnumerable <ProjectKey> projectKeys = Groups.Cast <ListViewGroup>().Select(x => (ProjectKey)x.Tag); BeginUpdate(); // Add missing merge requests and update existing ones foreach (ProjectKey projectKey in projectKeys) { if (isGroupCollapsed(projectKey)) { continue; } foreach (FullMergeRequestKey fmk in getAllProjectItems(projectKey)) { ListViewItem item = Items.Cast <ListViewItem>().FirstOrDefault( x => ((FullMergeRequestKey)x.Tag).Equals(fmk)); // item=`null` if not found if (item == null) { item = createListViewMergeRequestItem(fmk); Items.Add(item); } else { item.Tag = fmk; } setListViewSubItemsTags(item, fmk); } } // Delete summary items from groups that are no longer collapsed for (int index = Items.Count - 1; index >= 0; --index) { FullMergeRequestKey fmk = (FullMergeRequestKey)Items[index].Tag; if (!isGroupCollapsed(Items[index].Group) && isSummaryItem(Items[index])) { Items.RemoveAt(index); } } // Remove normal items from collapsed groups for (int index = Items.Count - 1; index >= 0; --index) { if (isGroupCollapsed(Items[index].Group)) { Items.RemoveAt(index); } } // Create summary items foreach (ListViewGroup group in Groups) { if (isGroupCollapsed(group)) { string[] subitems = Enumerable.Repeat(String.Empty, Columns.Count).ToArray(); FullMergeRequestKey fmk = new FullMergeRequestKey(getGroupProjectKey(group), null); ListViewItem item = createListViewMergeRequestItem(fmk); Items.Add(item); setListViewSubItemsTagsForSummary(item); } } // Remove deleted merge requests for (int index = Items.Count - 1; index >= 0; --index) { FullMergeRequestKey fmk = (FullMergeRequestKey)Items[index].Tag; if (!isGroupCollapsed(fmk.ProjectKey) && !getAllProjectItems(fmk.ProjectKey).Any(x => x.MergeRequest.IId == fmk.MergeRequest.IId)) { Items.RemoveAt(index); } } // Hide filtered ones for (int index = Items.Count - 1; index >= 0; --index) { FullMergeRequestKey fmk = (FullMergeRequestKey)Items[index].Tag; bool isCollapsed = isGroupCollapsed(fmk.ProjectKey); bool removeItem = false; if (isCollapsed) { bool isThereAnyMatchingItem = getMatchingFilterProjectItems(fmk.ProjectKey).Any(); removeItem = !isThereAnyMatchingItem; } else { bool doesItemMatchFilter = doesMatchFilter(fmk.MergeRequest); removeItem = !doesItemMatchFilter; } if (removeItem) { Items.RemoveAt(index); } } // update a number of MR which is probably displayed _suppressSelectionChange = true; try { Groups.Cast <ListViewGroup>().ToList().ForEach(group => updateGroupCaption(group)); } finally { _suppressSelectionChange = false; } recalcRowHeightForMergeRequestListView(); EndUpdate(); }