Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Commit for Publication (Revised)

  • Loading branch information...
commit d897540e86ad4e2cd795334396b2ad281e424904 0 parents
John Atten xivSolutions authored
Showing with 2,418 additions and 0 deletions.
  1. +152 −0 GroupedListControl/GroupListControl.cs
  2. +105 −0 GroupedListControl/GroupedListControl.csproj
  3. +29 −0 GroupedListControl/GroupedListControl.sln
  4. BIN  GroupedListControl/GroupedListControl.sln.docstates.suo
  5. +925 −0 GroupedListControl/ListGroup.cs
  6. +18 −0 GroupedListControl/ListGroupColumnEventArgs.cs
  7. +19 −0 GroupedListControl/ListGroupEventArgs.cs
  8. +26 −0 GroupedListControl/ListGroupItemEventArgs.cs
  9. +21 −0 GroupedListControl/Program.cs
  10. +36 −0 GroupedListControl/Properties/AssemblyInfo.cs
  11. +98 −0 GroupedListControl/Properties/Resources.Designer.cs
  12. +136 −0 GroupedListControl/Properties/Resources.resx
  13. +30 −0 GroupedListControl/Properties/Settings.Designer.cs
  14. +7 −0 GroupedListControl/Properties/Settings.settings
  15. BIN  GroupedListControl/Resources/CollapsedGroupSmall_png_1616.png
  16. BIN  GroupedListControl/Resources/EmptyGroupSmall_png_1616.png
  17. BIN  GroupedListControl/Resources/ExpandedGroupSmall_png_1616.png
  18. +118 −0 GroupedListDemo/Form1.Designer.cs
  19. +203 −0 GroupedListDemo/Form1.cs
  20. +120 −0 GroupedListDemo/Form1.resx
  21. +93 −0 GroupedListDemo/GroupedListDemo.csproj
  22. +21 −0 GroupedListDemo/Program.cs
  23. +36 −0 GroupedListDemo/Properties/AssemblyInfo.cs
  24. +71 −0 GroupedListDemo/Properties/Resources.Designer.cs
  25. +117 −0 GroupedListDemo/Properties/Resources.resx
  26. +30 −0 GroupedListDemo/Properties/Settings.Designer.cs
  27. +7 −0 GroupedListDemo/Properties/Settings.settings
152 GroupedListControl/GroupListControl.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Windows.Forms.Layout;
+using System.Runtime.InteropServices;
+
+namespace GroupedListControl
+{
+
+ public class GroupListControl : FlowLayoutPanel
+ {
+
+ public GroupListControl()
+ {
+ // Default configuration. Adapt to suit your needs:
+ this.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
+ this.AutoScroll = true;
+ this.WrapContents = false;
+
+ // Add a local handler for the ControlAdded Event.
+ this.ControlAdded += new ControlEventHandler(GroupListControl_ControlAdded);
+ }
+
+
+ /// <summary>
+ /// COnsumed by the Win API calls below:
+ /// </summary>
+ private enum ScrollBarDirection
+ {
+ SB_HORZ = 0,
+ SB_VERT = 1,
+ SB_CTL = 2,
+ SB_BOTH = 3
+ }
+
+
+ /// <summary>
+ /// Disables the horizontal scrollbar in the primary container control.
+ /// Individual ListGroups within the GroupList have their own scrollbars
+ /// if needed.
+ /// </summary>
+ /// <param name="hWnd"></param>
+ /// <param name="wBar"></param>
+ /// <param name="bShow"></param>
+ /// <returns></returns>
+ protected override void WndProc(ref System.Windows.Forms.Message m)
+ {
+ // Call to unmanaged WinAPI:
+ ShowScrollBar(this.Handle, (int)ScrollBarDirection.SB_HORZ, false);
+ base.WndProc(ref m);
+ }
+
+
+ /// <summary>
+ /// Imported from WinAPI: Method to control Scrollbar visibility.
+ /// </summary>
+ /// <param name="hWnd"></param>
+ /// <param name="wBar"></param>
+ /// <param name="bShow"></param>
+ /// <returns></returns>
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool ShowScrollBar(IntPtr hWnd, int wBar, bool bShow);
+
+
+ /// <summary>
+ /// Handles the ControlAdded Event for the current instance.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ void GroupListControl_ControlAdded(object sender, ControlEventArgs e)
+ {
+ ListGroup lg = (ListGroup)e.Control;
+ lg.Width = this.Width;
+ lg.GroupCollapsed += new ListGroup.GroupExpansionHandler(lg_GroupCollapsed);
+ lg.GroupExpanded += new ListGroup.GroupExpansionHandler(lg_GroupExpanded);
+ }
+
+
+ /// <summary>
+ /// Gets or Sets a boolean value indicating whether multiple ListGroups
+ /// may be in the expanded state at the same time. When set to true, the current expanded
+ /// ListGroup is collapsed when a new ListGroup is expanded.
+ /// </summary>
+ public bool SingleItemOnlyExpansion { get; set; }
+
+
+ /// <summary>
+ /// Handles the Expanded event for the current instance.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ void lg_GroupExpanded(object sender, EventArgs e)
+ {
+ // Grab a reference to the ListGroup which sent the message:
+ ListGroup expanded = (ListGroup)sender;
+
+ // If Single item only expansion, collapse all ListGroups in except
+ // the one currently exanding:
+ if(this.SingleItemOnlyExpansion)
+ {
+ this.SuspendLayout();
+ foreach(ListGroup lg in this.Controls)
+ {
+ if (!lg.Equals(expanded))
+ lg.Collapse();
+ }
+ this.ResumeLayout(true);
+ }
+
+ }
+
+
+ /// <summary>
+ /// Handles the Collapsed event for the current instance.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ void lg_GroupCollapsed(object sender, EventArgs e)
+ {
+ // No need.
+ }
+
+
+ /// <summary>
+ /// Expands all listgroups contained in the current instance.
+ /// </summary>
+ public void ExpandAll()
+ {
+ foreach(ListGroup lg in this.Controls)
+ {
+ lg.Expand();
+ }
+ }
+
+
+ /// <summary>
+ /// Collapses all ListGroups contained in the current instance.
+ /// </summary>
+ public void CollapseAll()
+ {
+ foreach (ListGroup lg in this.Controls)
+ {
+ lg.Collapse();
+ }
+ }
+
+ }
+
+}
105 GroupedListControl/GroupedListControl.csproj
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{2C43437C-5E27-48BE-BAC3-A3D0CDB30BFB}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>GroupedListControl</RootNamespace>
+ <AssemblyName>GroupedListControl</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <StartupObject />
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Deployment" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="GroupListControl.cs">
+ <SubType>Component</SubType>
+ </Compile>
+ <Compile Include="ListGroup.cs">
+ <SubType>Component</SubType>
+ </Compile>
+ <Compile Include="ListGroupColumnEventArgs.cs" />
+ <Compile Include="ListGroupItemEventArgs.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Resources.resx</DependentUpon>
+ <DesignTime>True</DesignTime>
+ </Compile>
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\CollapsedGroup_png_1616.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\ExpandedGroup_png_1616.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\CollapsedGroupSmall_png_1616.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\ExpandedGroupSmall_png_1616.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\EmptyGroupSmall_png_1616.png" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
29 GroupedListControl/GroupedListControl.sln
@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GroupedListControl", "GroupedListControl.csproj", "{2C43437C-5E27-48BE-BAC3-A3D0CDB30BFB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GroupedListDemo", "..\GroupedListDemo\GroupedListDemo.csproj", "{B90BCCEB-6690-44D2-94CC-8C16D1FC8EA6}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2C43437C-5E27-48BE-BAC3-A3D0CDB30BFB} = {2C43437C-5E27-48BE-BAC3-A3D0CDB30BFB}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2C43437C-5E27-48BE-BAC3-A3D0CDB30BFB}.Debug|x86.ActiveCfg = Debug|x86
+ {2C43437C-5E27-48BE-BAC3-A3D0CDB30BFB}.Debug|x86.Build.0 = Debug|x86
+ {2C43437C-5E27-48BE-BAC3-A3D0CDB30BFB}.Release|x86.ActiveCfg = Release|x86
+ {2C43437C-5E27-48BE-BAC3-A3D0CDB30BFB}.Release|x86.Build.0 = Release|x86
+ {B90BCCEB-6690-44D2-94CC-8C16D1FC8EA6}.Debug|x86.ActiveCfg = Debug|x86
+ {B90BCCEB-6690-44D2-94CC-8C16D1FC8EA6}.Debug|x86.Build.0 = Debug|x86
+ {B90BCCEB-6690-44D2-94CC-8C16D1FC8EA6}.Release|x86.ActiveCfg = Release|x86
+ {B90BCCEB-6690-44D2-94CC-8C16D1FC8EA6}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
BIN  GroupedListControl/GroupedListControl.sln.docstates.suo
Binary file not shown
925 GroupedListControl/ListGroup.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.Windows.Forms.Layout;
+using System.Runtime.InteropServices;
+using System.ComponentModel;
+
+
+
+namespace GroupedListControl
+{
+ public class ListGroup : ListView
+ {
+
+ #region MEMBER DECLARATIONS
+
+ // The area occupied by the ListView header.
+ private Rectangle _headerRect;
+
+ // The default ContextMenu strip, which needs to be left alone by the client:
+ private ContextMenuStrip defaultContextMenuStrip;
+
+
+ #region DELEGATES AND EVENT DEFINITIONS
+
+ // NOTE: The events and delegates related to Column and Item Addition/Removal are
+ // called by the inner classes ListGroupColumnCollection and LIstGroupItemCollection.
+ // The proper function of the control depends upon these.
+
+ // Delegates to handle Column addition and removal Events:
+ public delegate void ColumnAddedHandler(object sender, ListGroupColumnEventArgs e);
+ public delegate void ColumnRangeAddedHandler(object sender, EventArgs e);
+ public delegate void ColumnRemovedHandler(object sender, ListGroupColumnEventArgs e);
+
+ // Events related to Column Addition and removal:
+ public event ColumnAddedHandler ColumnAdded;
+ public event ColumnRangeAddedHandler ColumnRangeAdded;
+ public event ColumnRemovedHandler ColumnRemoved;
+
+ // Delegates to handle Item Addition and Removal events:
+ public delegate void ItemAddedHandler(object sender, ListGroupItemEventArgs e);
+ public delegate void ItemRangeAddedHandler(object sender, ListGroupItemEventArgs e);
+ public delegate void ItemRemovedHandler(object sender, ListGroupItemEventArgs e);
+ public delegate void ItemRemovedAtHandler(object sender, ListGroupItemEventArgs e);
+
+ // Events related to Item Addition and Removal:
+ public event ItemAddedHandler ItemAdded;
+ public event ItemRangeAddedHandler ItemRangeAdded;
+ public event ItemRemovedHandler ItemRemoved;
+ public event ItemRemovedAtHandler ItemRemovedAt;
+
+ // Delegate and related events to process Group Expansion and Collapse:
+ public delegate void GroupExpansionHandler(object sender, EventArgs e);
+ public event GroupExpansionHandler GroupExpanded;
+ public event GroupExpansionHandler GroupCollapsed;
+
+ // DElegate and related eevents to handle Listview Header Right Clicks:
+ public delegate void ColumnRightClickHandler(object sender, ColumnClickEventArgs e);
+ public event ColumnRightClickHandler ColumnRightClick;
+
+
+ #endregion // DELEGATES AND EVENT DEFINITIONS
+
+
+ #region INNER CLASS DECLARATIONS
+
+ private ListGroupItemCollection _Items;
+ private ListGroupColumnCollection _Columns;
+
+
+ #endregion // INNER CLASS DECLARATION
+
+
+ #region LOCAL STATIC MEMBERS
+
+ // Text strings used as Image keys for the expanded/Collapsed image in the
+ // left-most columnHeader:
+ static string COLLAPSED_IMAGE_KEY = "CollapsedImage";
+ static string EXPANDED_IMAGE_KEY = "ExpandedImageKey";
+ static string EMPTY_IMAGE_KEY = "EmptyImageKey";
+
+ // "Magic number" approximates the height of the List View Column Header:
+ static int HEADER_HEIGHT = 25;
+
+
+ #endregion // LOCAL STATIC MEMBERS
+
+
+ #endregion MEMBER DECLARATIONS
+
+
+ #region CONSTRUCTOR
+
+ public ListGroup() : base()
+ {
+ defaultContextMenuStrip = new ContextMenuStrip();
+ defaultContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(regularListViewMenu_Opening);
+ this.ContextMenuStrip = defaultContextMenuStrip;
+
+ _Columns = new ListGroupColumnCollection(this);
+ _Items = new ListGroupItemCollection(this);
+
+ // The Imagelist is used to hold images for the expanded and contracted icons in the
+ // Left-most columnheader:
+ this.SmallImageList = new ImageList();
+
+ // The tilting arrow images are available in the app resources:
+ this.SmallImageList.Images.Add(COLLAPSED_IMAGE_KEY, Properties.Resources.CollapsedGroupSmall_png_1616);
+ this.SmallImageList.Images.Add(EXPANDED_IMAGE_KEY, Properties.Resources.ExpandedGroupSmall_png_1616);
+ this.SmallImageList.Images.Add(EMPTY_IMAGE_KEY, Properties.Resources.EmptyGroupSmall_png_1616);
+
+
+ // The stateImageList is used as a hack method to allow larger Row Heights:
+ this.StateImageList = new ImageList();
+
+ // Default configuration (for this sample. Obviously, configure to fit your needs:
+ this.View = System.Windows.Forms.View.Details;
+ this.FullRowSelect = true;
+ this.GridLines = true;
+ this.LabelEdit = false;
+ this.Margin = new Padding(0);
+ this.SetAutoSizeMode(AutoSizeMode.GrowAndShrink);
+ this.MaximumSize = new System.Drawing.Size(1000, 300);
+
+ // Subscribe to local Events:
+ this.ColumnClick += new ColumnClickEventHandler(ListGroup_ColumnClick);
+
+ }
+
+
+ #endregion // CONSTRUCTOR
+
+
+ #region PROPERTIES
+
+
+ /// <summary>
+ /// Hides the ListViewItemCollection internal to the base class, and uses the
+ /// new implementation defined as an inner class, which sources an "ItemAdded" Event:
+ /// </summary>
+ public new ListGroupItemCollection Items
+ {
+ get { return _Items; }
+ }
+
+
+
+ /// <summary>
+ /// Hides the ColumnHeaderCollection internal to the base class, and uses the
+ /// new implementation defined as an inner class, which sources a "ColumnAdded" Event:
+ /// </summary>
+ public new ListGroupColumnCollection Columns
+ {
+ get { return _Columns; }
+ }
+
+
+
+ /// <summary>
+ /// Gets the total width of all column headers in the control:
+ /// </summary>
+ public int TotalColumnWidths
+ {
+ get { return this.Columns.TotalColumnWidths; }
+ }
+
+
+ /// <summary>
+ /// Gets or sets the height of the ListViewItem rows.
+ /// </summary>
+ public int RowHeight
+ {
+ get { return this.StateImageList.ImageSize.Height; }
+ set
+ {
+ this.StateImageList.ImageSize = new System.Drawing.Size(value, value);
+ }
+ }
+
+
+
+ #endregion // PROPERTIES
+
+
+ #region ITEM ADDITION AND REMOMVAL EVENT HANDLING (Local)
+
+
+
+ /// <summary>
+ /// Raises the ItemAdded Event when a new item is
+ /// added to the items collection.
+ /// </summary>
+ /// <param name="lvi"></param>
+ private void OnItemAdded(ListViewItem lvi)
+ {
+ this.SetControlHeight();
+ if(ItemAdded != null)
+ this.ItemAdded(this, new ListGroupItemEventArgs(lvi));
+ }
+
+
+ /// <summary>
+ /// Raises the ItemRangeAdded Event when a range of items are
+ /// added to the items collection.
+ /// </summary>
+ /// <param name="Items"></param>
+ private void OnItemRangeAdded(ListViewItem[] Items)
+ {
+ this.SetControlHeight();
+ if(ItemRangeAdded != null)
+ this.ItemRangeAdded(this, new ListGroupItemEventArgs(Items));
+ }
+
+
+ /// <summary>
+ /// Raises the ItemRemoved Event when an item is
+ /// removed from the items collection.
+ /// </summary>
+ /// <param name="Item"></param>
+ private void OnItemRemoved(ListViewItem Item)
+ {
+ this.Height = this.PreferredControlHeight();
+ if(ItemRemoved != null)
+ this.ItemRemoved(this, new ListGroupItemEventArgs(Item));
+ }
+
+
+ /// <summary>
+ /// Raises the ItemRemovedAt Event when an item is
+ /// removed from the items collection.
+ /// </summary>
+ /// <param name="index"></param>
+ /// <param name="Item"></param>
+ private void OnItemRemovedAt(int index, ListViewItem Item)
+ {
+ this.Height = this.PreferredControlHeight();
+ if(this.ItemRemovedAt != null)
+ this.ItemRemovedAt(this, new ListGroupItemEventArgs(Item));
+ }
+
+
+
+ #endregion // ITEM ADDITION AND REMOVAL EVENT HANDLING (Local)
+
+
+ #region COLUMNHEADER ADDITION AND REMOVAL EVENT HANDLING (Local)
+
+
+ /// <summary>
+ /// Raises the ColumnAdded Event when a new column is
+ /// added to the ColumnHeaders collection.
+ /// </summary>
+ /// <param name="ColumnIndex"></param>
+ private void OnColumnAdded(int ColumnIndex)
+ {
+ if (ColumnIndex == 0)
+ {
+ this.Columns[0].ImageKey = EMPTY_IMAGE_KEY;
+ this.SetControlHeight();
+ }
+
+ if(this.ColumnAdded != null)
+ this.ColumnAdded(this, new ListGroupColumnEventArgs(ColumnIndex));
+
+ }
+
+
+
+ void ListGroup_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
+ {
+ if (this.Height > HEADER_HEIGHT)
+
+ // When the width of a column is changed, the Horizontal Scrollbar might
+ // appear. If so, the height of this ListGroup will be adjusted slightly to
+ // accomodate the scrollbar without partially obscuring the last visible item:
+ this.Height = this.PreferredControlHeight();
+ }
+
+
+
+ /// <summary>
+ /// Raises the ColumnRangeAdded Event when a range of new columns are
+ /// added to the ColumnHeaders collection.
+ /// </summary>
+ /// <param name="Columns"></param>
+ private void OnColumnRangeAdded(ColumnHeader[] Columns)
+ {
+ if(this.Columns.Count > 0)
+ this.Columns[0].ImageKey = EXPANDED_IMAGE_KEY;
+
+ if(this.ColumnRangeAdded != null)
+ this.ColumnRangeAdded(this, new EventArgs());
+ }
+
+
+
+ /// <summary>
+ /// Raises the ColumnRemoved Event when a column is
+ /// remmoved from the ColumnHeaders collection.
+ /// </summary>
+ private void OnColumnRemoved(int ColumnIndex)
+ {
+ // REMOVE ColumnWidthChanged Handler before removing columns:
+ this.ColumnWidthChanged -= new ColumnWidthChangedEventHandler(ListGroup_ColumnWidthChanged);
+
+ this.Height = this.PreferredControlHeight();
+
+ // RESTORE ColumnWidthChanged Event Handler:
+ this.ColumnWidthChanged += new ColumnWidthChangedEventHandler(ListGroup_ColumnWidthChanged);
+
+
+ if(this.ColumnRemoved != null)
+ this.ColumnRemoved(this, new ListGroupColumnEventArgs(ColumnIndex));
+ }
+
+
+
+ /// <summary>
+ /// Handles the ListGroup ColumnClick Event
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ void ListGroup_ColumnClick(object sender, ColumnClickEventArgs e)
+ {
+ int columnClicked = e.Column;
+
+ // The first column (Column[0]) is what activates the expansion/collapse of the
+ // List view item group:
+ if (columnClicked == 0)
+ {
+ this.SuspendLayout();
+ this.SetControlHeight();
+ this.ResumeLayout();
+ }
+ }
+
+
+ #endregion // COLUMNHEADER ADDITION AND REMOMVAL EVENT HANDLING (Local)
+
+
+ #region CONTROL EXPANSION/COLLAPSE
+
+
+ private int PreferredControlHeight()
+ {
+ int output = HEADER_HEIGHT;
+ int rowHeight = 0;
+
+ // determine the height of an individual list item:
+ if(this.Items.Count > 0)
+ rowHeight = this.Items[0].Bounds.Height;
+
+ // In case the horizontal scrollbar makes an appearance, we will
+ // need to modify the height of the expanded list so that it does not
+ // obscure the last item (default is 10 px to leave a little space no mattter what:
+ int horizScrollBarOffset = 10;
+
+ // if the Width of the columns is greater than the width of the control, the vertical scroll bar will be shown.
+ // Increase that offset height by the height of the scrollbar (approximately the same as the height of a row):
+ if (this.Columns.TotalColumnWidths > this.Width)
+ horizScrollBarOffset = rowHeight + 10;
+
+ // Increase the height of the control to accomodate the Columnheader, all of the current items,
+ // and the value of the horizontal scroll bar (if present):
+ output = HEADER_HEIGHT + (this.Items.Count) * rowHeight + horizScrollBarOffset + this.Groups.Count * HEADER_HEIGHT;
+
+ return output;
+ }
+
+
+ /// <summary>
+ /// Causes the list of items to expand, showing all items in the
+ /// Items collection.
+ /// </summary>
+ public void Expand()
+ {
+ if (this.Columns.Count > 0)
+ {
+ this.Height = this.PreferredControlHeight();
+
+ if (this.Items.Count > 0)
+ // Set the image in the first column to indicate an expanded state:
+ this.Columns[0].ImageKey = EXPANDED_IMAGE_KEY;
+ else
+ // Set the image in the first column to indicate an empty state:
+ this.Columns[0].ImageKey = EMPTY_IMAGE_KEY;
+
+ this.Scrollable = true;
+
+ // Raise the Expanded event to notify client code that the ListGroup has expanded:
+ if (this.GroupExpanded != null)
+ this.GroupExpanded(this, new EventArgs());
+ }
+ }
+
+
+
+ /// <summary>
+ /// Causes the Displayed list of items to collapse, hiding all items and
+ /// displaying only the columnheaders.
+ /// </summary>
+ public void Collapse()
+ {
+ if (this.Columns.Count > 0)
+ {
+ this.Scrollable = false;
+
+ // Collapse the ListGroup to show only the header:
+ this.Height = HEADER_HEIGHT;
+
+ if (this.Items.Count > 0)
+ // Set the image in the first column to indicate a collapsed state:
+ this.Columns[0].ImageKey = COLLAPSED_IMAGE_KEY;
+ else
+ // Set the image in the first column to indicate an empty state:
+ this.Columns[0].ImageKey = EMPTY_IMAGE_KEY;
+
+ // Raise the Collapsed event to notify client code that the ListGroup has expanded:
+ if (this.GroupCollapsed != null)
+ this.GroupCollapsed(this, new EventArgs());
+ }
+
+ }
+
+
+ /// <summary>
+ /// Adjusts the item display area of the control in response to changes in the
+ /// expanded or collapsed state of the control.
+ /// </summary>
+ public void SetControlHeight()
+ {
+ if (this.Height == HEADER_HEIGHT && this.Items.Count != 0)
+ this.Expand();
+ else
+ this.Collapse();
+ }
+
+ #endregion CONTROL EXPANSION/COLLAPSE
+
+
+ #region ListGroupItemCollection
+
+
+ // Core Concept in this section was adapted from: http://www.codeproject.com/Articles/4406/An-Observer-Pattern-and-an-Extended-ListView-Event
+
+ /// <summary>
+ /// Inner class defined for ListGroup to contain List items. Derived from ListViewItemCollection
+ /// and modified to source events indicating item addition and removal.
+ /// </summary>
+ public class ListGroupItemCollection : System.Windows.Forms.ListView.ListViewItemCollection
+ {
+ private ListGroup _Owner;
+ public ListGroupItemCollection(ListGroup Owner) : base(Owner)
+ {
+ _Owner = Owner;
+ }
+
+
+ /// <summary>
+ /// New implementation of Add method hides Add method defined on base class
+ /// and causes an event to be sourced informing the parent about item additions.
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="text"></param>
+ /// <param name="imageIndex"></param>
+ /// <returns></returns>
+ public new ListViewItem Add(string key, string text, int imageIndex)
+ {
+ ListViewItem item = base.Add(key, text, imageIndex);
+ _Owner.OnItemAdded(item);
+ return item;
+ }
+
+
+ /// <summary>
+ /// New implementation of Add method hides Add method defined on base class
+ /// and causes an event to be sourced informing the parent about item additions.
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="text"></param>
+ /// <param name="imageIndex"></param>
+ /// <returns></returns>
+ public new ListViewItem Add(string text)
+ {
+ ListViewItem item = base.Add(text);
+ _Owner.OnItemAdded(item);
+ return item;
+ }
+
+
+
+ /// <summary>
+ /// New implementation of Add method hides Add method defined on base class
+ /// and causes an event to be sourced informing the parent about item additions.
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="text"></param>
+ /// <param name="imageKey"></param>
+ /// <returns></returns>
+ public new ListViewItem Add(string key, string text, string imageKey)
+ {
+ ListViewItem item = base.Add(key, text, imageKey);
+ _Owner.OnItemAdded(item);
+ return item;
+ }
+
+
+ /// <summary>
+ /// New implementation of Add method hides Add method defined on base class
+ /// and causes an event to be sourced informing the parent about item additions.
+ /// </summary>
+ /// <param name="text"></param>
+ /// <param name="imageIndex"></param>
+ /// <returns></returns>
+ public new ListViewItem Add(string text, int imageIndex)
+ {
+ ListViewItem item = base.Add(text, imageIndex);
+ _Owner.OnItemAdded(item);
+ return item;
+ }
+
+
+
+ /// <summary>
+ /// New implementation of Add method hides Add method defined on base class
+ /// and causes an event to be sourced informing the parent about item additions.
+ /// </summary>
+ /// <param name="text"></param>
+ /// <param name="imageKey"></param>
+ /// <returns></returns>
+ public new ListViewItem Add(string text, string imageKey)
+ {
+ ListViewItem item = base.Add(text, imageKey);
+ _Owner.OnItemAdded(item);
+ return item;
+ }
+
+
+
+ /// <summary>
+ /// New implementation of Add method hides Add method defined on base class
+ /// and causes an event to be sourced informing the parent about item additions.
+ /// </summary>
+ /// <param name="Item"></param>
+ public new void Add(ListViewItem Item)
+ {
+ base.Add(Item);
+ _Owner.OnItemAdded(Item);
+ }
+
+
+
+ /// <summary>
+ /// New implementation of Add method hides Add method defined on base class
+ /// and causes an event to be sourced informing the parent about item additions.
+ /// </summary>
+ /// <param name="Item"></param>
+ public new void AddRange(ListViewItem[] Item)
+ {
+ base.AddRange(Item);
+ _Owner.OnItemRangeAdded(Item);
+ }
+
+
+
+ /// <summary>
+ /// New implementation of Remove method hides Remove method defined on base class
+ /// and causes an event to be sourced informing the parent about item Removals.
+ /// </summary>
+ /// <param name="Item"></param>
+ public new void Remove(ListViewItem Item)
+ {
+ base.Remove(Item);
+ _Owner.OnItemRemoved(Item);
+ }
+
+
+ /// <summary>
+ /// New implementation of Remove method hides Remove method defined on base class
+ /// and causes an event to be sourced informing the parent about item Removals.
+ /// </summary>
+ /// <param name="index"></param>
+ public new void RemoveAt(int index)
+ {
+ System.Windows.Forms.ListViewItem Item = this[index];
+ base.RemoveAt(index);
+ _Owner.OnItemRemovedAt(index, Item);
+ }
+
+ } // ListGroupItemCollection
+
+
+ #endregion // ListGroupItemCollection
+
+
+ #region ListGroupColumnCollection
+
+
+ // Core Concept in this section was adapted from: http://www.codeproject.com/Articles/4406/An-Observer-Pattern-and-an-Extended-ListView-Event
+
+ /// <summary>
+ /// Inner class defined for ListGroup to contain ColumnHeaders. Derived from ListView.ColumnHeaderCollection
+ /// and modified to source events indicating column addition and removal.
+ /// </summary>
+ public class ListGroupColumnCollection : ListView.ColumnHeaderCollection
+ {
+ // Reference to the containing ListGroup Control
+ private ListGroup _Owner;
+
+ public ListGroupColumnCollection(ListGroup Owner) : base(Owner)
+ {
+ _Owner = Owner;
+ }
+
+
+
+ /// <summary>
+ /// Gets the total width of all columns currently defined in the control.
+ /// </summary>
+ public int TotalColumnWidths
+ {
+ get
+ {
+ int totalColumnWidths = 0;
+ foreach (ColumnHeader clm in this)
+ totalColumnWidths = totalColumnWidths + clm.Width;
+ return totalColumnWidths;
+ }
+ }
+
+
+ /// <summary>
+ /// Adds a column to the current collection and raises the OnColumnAddedEvent on the parent control.
+ /// </summary>
+ /// <param name="value"></param>
+ /// <returns></returns>
+ public new int Add(ColumnHeader value)
+ {
+ int clm = base.Add(value);
+ _Owner.OnColumnAdded(clm);
+ return clm;
+ }
+
+
+ /// <summary>
+ /// Adds a column to the current collection and raises the OnColumnAddedEvent on the parent control.
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="text"></param>
+ /// <returns></returns>
+ public new ColumnHeader Add(string key, string text)
+ {
+ ColumnHeader clm = base.Add(key, text);
+ _Owner.OnColumnAdded(clm.Index);
+ return clm;
+ }
+
+
+ /// <summary>
+ /// Adds a column to the current collection and raises the OnColumnAddedEvent on the parent control.
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="text"></param>
+ /// <param name="width"></param>
+ /// <returns></returns>
+ public new ColumnHeader Add(string key, string text, int width)
+ {
+ ColumnHeader clm = base.Add(key, text, width);
+ _Owner.OnColumnAdded(clm.Index);
+ return clm;
+ }
+
+
+ /// <summary>
+ /// Adds a column to the current collection and raises the OnColumnAddedEvent on the parent control.
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="text"></param>
+ /// <param name="width"></param>
+ /// <param name="textAlign"></param>
+ /// <param name="imageIndex"></param>
+ /// <returns></returns>
+ public new ColumnHeader Add(string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
+ {
+ ColumnHeader clm = base.Add(key, text, width, textAlign, imageIndex);
+ _Owner.OnColumnAdded(clm.Index);
+ return clm;
+ }
+
+
+ /// <summary>
+ /// Adds a column to the current collection and raises the OnColumnAddedEvent on the parent control.
+ /// </summary>
+ /// <param name="key"></param>
+ /// <param name="text"></param>
+ /// <param name="width"></param>
+ /// <param name="textAlign"></param>
+ /// <param name="imageKey"></param>
+ /// <returns></returns>
+ public new ColumnHeader Add(string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
+ {
+ ColumnHeader clm = base.Add(key, text, width, textAlign, imageKey);
+ _Owner.OnColumnAdded(clm.Index);
+ return clm;
+ }
+
+
+ /// <summary>
+ /// Adds a column to the current collection and raises the OnColumnAddedEvent on the parent control.
+ /// </summary>
+ /// <param name="text"></param>
+ /// <returns></returns>
+ public new ColumnHeader Add(string text)
+ {
+ ColumnHeader clm = base.Add(text);
+ _Owner.OnColumnAdded(clm.Index);
+ return clm;
+ }
+
+
+ /// <summary>
+ /// Adds a column to the current collection and raises the OnColumnAddedEvent on the parent control.
+ /// </summary>
+ /// <param name="text"></param>
+ /// <param name="width"></param>
+ /// <returns></returns>
+ public new ColumnHeader Add(string text, int width)
+ {
+ ColumnHeader clm = base.Add(text, width);
+ _Owner.OnColumnAdded(clm.Index);
+ return clm;
+ }
+
+
+ /// <summary>
+ /// Adds a column to the current collection and raises the OnColumnAddedEvent on the parent control.
+ /// </summary>
+ /// <param name="text"></param>
+ /// <param name="width"></param>
+ /// <param name="textAlign"></param>
+ /// <returns></returns>
+ public new ColumnHeader Add(string text, int width, HorizontalAlignment textAlign)
+ {
+ ColumnHeader clm = base.Add(text, width, textAlign);
+ _Owner.OnColumnAdded(clm.Index);
+ return clm;
+ }
+
+
+ /// <summary>
+ /// Adds a range of columns to the current collection and raises the OnColumnAdded Event on the parent control.
+ /// </summary>
+ /// <param name="values"></param>
+ public new void AddRange(ColumnHeader[] values)
+ {
+ base.AddRange(values);
+ _Owner.OnColumnRangeAdded(values);
+ }
+
+
+ /// <summary>
+ /// Removes a column from the current collection and raises the OnColumnRemoved Event on the parent control.
+ /// </summary>
+ /// <param name="column"></param>
+ public new void Remove(ColumnHeader column)
+ {
+ int index = column.Index;
+ base.Remove(column);
+ _Owner.OnColumnRemoved(index);
+ }
+
+
+ /// <summary>
+ /// Removes a column from the current collection and raises the OnColumnRemoved Event on the parent control.
+ /// </summary>
+ /// <param name="index"></param>
+ public new void RemoveAt(int index)
+ {
+ ColumnHeader clm = this[index];
+ base.RemoveAt(index);
+ _Owner.OnColumnRemoved(index);
+ }
+
+ /// <summary>
+ /// Removes a column from the current collection and raises the OnColumnRemoved Event on the parent control.
+ /// </summary>
+ /// <param name="key"></param>
+ public new void RemoveByKey(string key)
+ {
+ ColumnHeader clm = this[key];
+ int index = clm.Index;
+ base.RemoveByKey(key);
+ _Owner.OnColumnRemoved(index);
+ }
+
+
+ public new void Clear()
+ {
+ base.Clear();
+ }
+
+ } // ListGroupColumnCollection
+
+
+
+
+
+ #endregion // ListGroupColumnCollection
+
+
+ #region ListViewColumnHeader Right Click Event Sourcing
+
+ // The following code was adapted from: http://www.codeproject.com/Articles/23330/Handling-Right-Click-Events-in-ListView-Column-Hea
+
+ // This returns an array of ColumnHeaders in the order they are
+ // displayed by the ListView.
+ private static ColumnHeader[] GetOrderedHeaders(ListView lv)
+ {
+ ColumnHeader[] arr = new ColumnHeader[lv.Columns.Count];
+
+ foreach (ColumnHeader header in lv.Columns)
+ {
+ arr[header.DisplayIndex] = header;
+ }
+
+ return arr;
+ }
+
+
+ // Called when the user right-clicks anywhere in the ListView, including the
+ // header bar. It displays the appropriate context menu for the data row or
+ // header that was right-clicked.
+ private void regularListViewMenu_Opening(object sender, CancelEventArgs e)
+ {
+ // This call indirectly calls EnumWindowCallBack which sets _headerRect
+ // to the area occupied by the ListView's header bar.
+ EnumChildWindows(this.Handle, new EnumWinCallBack(EnumWindowCallBack), IntPtr.Zero);
+
+ // If the mouse position is in the header bar, cancel the display
+ // of the regular context menu and display the column header context menu instead.
+ if (_headerRect.Contains(Control.MousePosition))
+ {
+ e.Cancel = true;
+
+ // The xoffset is how far the mouse is from the left edge of the header.
+ int xoffset = Control.MousePosition.X - _headerRect.Left;
+
+ // Iterate through the column headers in the order they are displayed, adding up
+ // their widths as we go. When the sum exceeds the xoffset, we know the mouse
+ // is on the current header.
+ int sum = 0;
+ foreach (ColumnHeader header in GetOrderedHeaders(this))
+ {
+ sum += header.Width;
+ if (sum > xoffset)
+ {
+ OnColumnRightClick(header);
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Allow the regular context menu to be displayed.
+ // I am not using the regular menu, so this is empty.
+ }
+ }
+
+ // Called when the specified column header is right-clicked.
+ private void OnColumnRightClick(ColumnHeader header)
+ {
+ this.ColumnRightClick(this, new ColumnClickEventArgs(header.Index));
+ }
+
+
+ // This should get called with the only child window of the ListView,
+ // which should be the header bar.
+ private bool EnumWindowCallBack(IntPtr hwnd, IntPtr lParam)
+ {
+ // Determine the rectangle of the ListView header bar and save it in _headerRect.
+ RECT rct;
+
+ if (!GetWindowRect(hwnd, out rct))
+ {
+ _headerRect = Rectangle.Empty;
+ }
+ else
+ {
+ _headerRect = new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top);
+ }
+
+ return false; // Stop the enum
+ }
+
+
+ // Delegate that is called for each child window of the ListView.
+ private delegate bool EnumWinCallBack(IntPtr hwnd, IntPtr lParam);
+
+ // Calls EnumWinCallBack for each child window of hWndParent (i.e. the ListView).
+ [DllImport("user32.Dll")]
+ private static extern int EnumChildWindows(IntPtr hWndParent, EnumWinCallBack callBackFunc, IntPtr lParam);
+
+ // Gets the bounding rectangle of the specified window (ListView header bar).
+ [DllImport("user32.dll")]
+ private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct RECT
+ {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+ }
+
+
+ #endregion // ListViewColumnHeader Right Click Event Sourcing
+ }
+
+
+
+}
18 GroupedListControl/ListGroupColumnEventArgs.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace GroupedListControl
+{
+ public class ListGroupColumnEventArgs : EventArgs
+ {
+ public ListGroupColumnEventArgs(int Columnindex)
+ {
+ this.ColumnIndex = ColumnIndex;
+ }
+
+ public int ColumnIndex { get; set; }
+ }
+}
19 GroupedListControl/ListGroupEventArgs.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace GroupedListControl
+{
+ class ListGroupEventArgs : System.EventArgs
+ {
+ public ListGroupEventArgs(ListGroup ListGroup)
+ {
+
+ }
+
+
+ public ListGroup ListGroup { get; set; }
+ }
+}
26 GroupedListControl/ListGroupItemEventArgs.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace GroupedListControl
+{
+ public class ListGroupItemEventArgs : EventArgs
+ {
+ public ListGroupItemEventArgs(ListViewItem Item)
+ {
+ this.Item = Item;
+ }
+
+
+ public ListGroupItemEventArgs(ListViewItem[] Items)
+ {
+ this.Items = Items;
+ }
+
+
+ public ListViewItem Item { get; set; }
+ public ListViewItem[] Items { get; set; }
+ }
+}
21 GroupedListControl/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace GroupedListControl
+{
+ static class Program
+ {
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run(new TestForm());
+ }
+ }
+}
36 GroupedListControl/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GroupedListControl")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("GroupedListControl")]
+[assembly: AssemblyCopyright("Copyright © 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("af04949a-995a-45fc-bb65-c69e34b2cb27")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
98 GroupedListControl/Properties/Resources.Designer.cs
@@ -0,0 +1,98 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.261
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace GroupedListControl.Properties {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GroupedListControl.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ internal static System.Drawing.Bitmap CollapsedGroup_png_1616 {
+ get {
+ object obj = ResourceManager.GetObject("CollapsedGroup_png_1616", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ internal static System.Drawing.Bitmap CollapsedGroupSmall_png_1616 {
+ get {
+ object obj = ResourceManager.GetObject("CollapsedGroupSmall_png_1616", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ internal static System.Drawing.Bitmap EmptyGroupSmall_png_1616 {
+ get {
+ object obj = ResourceManager.GetObject("EmptyGroupSmall_png_1616", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ internal static System.Drawing.Bitmap ExpandedGroup_png_1616 {
+ get {
+ object obj = ResourceManager.GetObject("ExpandedGroup_png_1616", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ internal static System.Drawing.Bitmap ExpandedGroupSmall_png_1616 {
+ get {
+ object obj = ResourceManager.GetObject("ExpandedGroupSmall_png_1616", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
136 GroupedListControl/Properties/Resources.resx
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+ <data name="CollapsedGroupSmall_png_1616" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>..\Resources\CollapsedGroupSmall_png_1616.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+ <data name="CollapsedGroup_png_1616" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>..\Resources\CollapsedGroup_png_1616.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+ <data name="EmptyGroupSmall_png_1616" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>..\Resources\EmptyGroupSmall_png_1616.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+ <data name="ExpandedGroupSmall_png_1616" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>..\Resources\ExpandedGroupSmall_png_1616.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+ <data name="ExpandedGroup_png_1616" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>..\Resources\ExpandedGroup_png_1616.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+</root>
30 GroupedListControl/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.261
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace GroupedListControl.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
7 GroupedListControl/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
BIN  GroupedListControl/Resources/CollapsedGroupSmall_png_1616.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  GroupedListControl/Resources/EmptyGroupSmall_png_1616.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  GroupedListControl/Resources/ExpandedGroupSmall_png_1616.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
118 GroupedListDemo/Form1.Designer.cs
@@ -0,0 +1,118 @@
+namespace GroupedListDemo
+{
+ partial class Form1
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.chkSingleItemOnlyMode = new System.Windows.Forms.CheckBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.groupListControl1 = new GroupedListControl.GroupListControl();
+ this.button1 = new System.Windows.Forms.Button();
+ this.button2 = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // chkSingleItemOnlyMode
+ //
+ this.chkSingleItemOnlyMode.AutoSize = true;
+ this.chkSingleItemOnlyMode.Location = new System.Drawing.Point(12, 52);
+ this.chkSingleItemOnlyMode.Name = "chkSingleItemOnlyMode";
+ this.chkSingleItemOnlyMode.Size = new System.Drawing.Size(224, 17);
+ this.chkSingleItemOnlyMode.TabIndex = 1;
+ this.chkSingleItemOnlyMode.Text = "Demo Single-Group-Only Expansion Mode";
+ this.chkSingleItemOnlyMode.UseVisualStyleBackColor = true;
+ this.chkSingleItemOnlyMode.CheckedChanged += new System.EventHandler(this.chkSingleItemOnlyMode_CheckedChanged);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Font = new System.Drawing.Font("Lucida Sans", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label1.Location = new System.Drawing.Point(12, 13);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(230, 18);
+ this.label1.TabIndex = 2;
+ this.label1.Text = "Grouped List Control Demo";
+ //
+ // groupListControl1
+ //
+ this.groupListControl1.AutoScroll = true;
+ this.groupListControl1.BackColor = System.Drawing.SystemColors.Control;
+ this.groupListControl1.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
+ this.groupListControl1.Location = new System.Drawing.Point(12, 75);
+ this.groupListControl1.Name = "groupListControl1";
+ this.groupListControl1.SingleItemOnlyExpansion = false;
+ this.groupListControl1.Size = new System.Drawing.Size(508, 363);
+ this.groupListControl1.TabIndex = 0;
+ this.groupListControl1.WrapContents = false;
+ //
+ // button1
+ //
+ this.button1.Location = new System.Drawing.Point(303, 46);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(106, 23);
+ this.button1.TabIndex = 3;
+ this.button1.Text = "Remove Column";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // button2
+ //
+ this.button2.Location = new System.Drawing.Point(415, 46);
+ this.button2.Name = "button2";
+ this.button2.Size = new System.Drawing.Size(105, 23);
+ this.button2.TabIndex = 4;
+ this.button2.Text = "Remove Item";
+ this.button2.UseVisualStyleBackColor = true;
+ this.button2.Click += new System.EventHandler(this.button2_Click);
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(532, 450);
+ this.Controls.Add(this.button2);
+ this.Controls.Add(this.button1);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.chkSingleItemOnlyMode);
+ this.Controls.Add(this.groupListControl1);
+ this.Name = "Form1";
+ this.Text = "Form1";
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private GroupedListControl.GroupListControl groupListControl1;
+ private System.Windows.Forms.CheckBox chkSingleItemOnlyMode;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.Button button2;
+ }
+}
+
203 GroupedListDemo/Form1.cs
@@ -0,0 +1,203 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using GroupedListControl;
+
+namespace GroupedListDemo
+{
+ public partial class Form1 : Form
+ {
+ // A ContextMenuStrip as member variable. We need to use this instead of the
+ // context menus available in each ListGroup:
+ ContextMenuStrip _ListGroupContextMenu;
+ ToolStripMenuItem _addOption = new ToolStripMenuItem("Add");
+ ToolStripMenuItem _editOption = new ToolStripMenuItem("Edit");
+ ToolStripMenuItem _deleteOption = new ToolStripMenuItem("Delete");
+
+ public Form1()
+ {
+ InitializeComponent();
+
+ // Set up the context menu to use with the GroupedList Items:
+ _ListGroupContextMenu = new ContextMenuStrip();
+
+ // Add some sample ContextMenuStrip Items:
+ _addOption = new ToolStripMenuItem("Add");
+ _addOption.Click += new EventHandler(addOption_Click);
+ _ListGroupContextMenu.Items.Add(_addOption);
+
+ _editOption = new ToolStripMenuItem("Edit");
+ _editOption.Click += new EventHandler(editOption_Click);
+ _ListGroupContextMenu.Items.Add(_editOption);
+
+ _deleteOption = new ToolStripMenuItem("Delete");
+ _deleteOption.Click += new EventHandler(deleteOption_Click);
+ _ListGroupContextMenu.Items.Add(_deleteOption);
+ }
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ // Create a GroupedListControl instance:
+ GroupListControl glc = this.groupListControl1;
+ glc.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+
+ // Add some sample columns:
+ for(int i = 1; i <=5; i++)
+ {
+ ListGroup lg = new ListGroup();
+ lg.Columns.Add("List Group " + i.ToString(), 120);
+ lg.Columns.Add("Group " + i + " SubItem 1", 150);
+ lg.Columns.Add("Group " + i + " Subitem 2", 150);
+ lg.Name = "Group " + i;
+
+ // Now add some sample items:
+ for (int j = 1; j <= 5; j++)
+ {
+ ListViewItem item = lg.Items.Add("Item " + j.ToString());
+ item.SubItems.Add(item.Text + " SubItem 1");
+ item.SubItems.Add(item.Text + " SubItem 2");
+ }
+
+ // Add handling for the columnRightClick Event:
+ lg.ColumnRightClick += new ListGroup.ColumnRightClickHandler(lg_ColumnRightClick);
+ lg.MouseClick += new MouseEventHandler(lg_MouseClick);
+
+ glc.Controls.Add(lg);
+ }
+ }
+
+
+
+ void lg_MouseClick(object sender, MouseEventArgs e)
+ {
+ ListGroup lg = (ListGroup)sender;
+
+ ListViewHitTestInfo info = lg.HitTest(e.X, e.Y);
+ ListViewItem item = info.Item;
+
+ if (e.Button == MouseButtons.Right)
+ {
+ // Tuck the Active ListGroup into the Tag property:
+ _ListGroupContextMenu.Tag = lg;
+
+ // Make sure the Delete and Edit options are enabled:
+ _editOption.Enabled = true;
+ _deleteOption.Enabled = true;
+
+ // Because we are not using the GroupedList's own ContextMenuStrip,
+ // we need to use the PointToClient method so that the menu appears
+ // in the correct position relative to the control:
+ _ListGroupContextMenu.Show(lg, lg.PointToClient(MousePosition));
+ }
+
+ }
+
+
+
+ void lg_ColumnRightClick(object sender, ColumnClickEventArgs e)
+ {
+ ListGroup lg = (ListGroup)sender;
+
+ // Tuck the Active ListGroup into the Tag property:
+ _ListGroupContextMenu.Tag = lg;
+
+ // If the header is right-clicked, the user has not indicated an item to edit or delete.
+ // Disable those options:
+ _editOption.Enabled = false;
+ _deleteOption.Enabled = false;
+
+ // Because we are not using the GroupedList's own ContextMenuStrip,
+ // we need to use the PointToClient method so that the menu appears
+ // in the correct position relative to the control:
+ _ListGroupContextMenu.Show(lg, lg.PointToClient(MousePosition));
+ }
+
+
+
+ void deleteOption_Click(object sender, EventArgs e)
+ {
+ var menuItem = (ToolStripMenuItem)sender;
+ var menu = menuItem.Owner;
+ var selectedGroup = (ListGroup)menu.Tag;
+
+ // Only one selected item allowed for this demo:
+ var selectedItem = selectedGroup.SelectedItems[0];
+
+ string groupName = selectedGroup.Name;
+ string itemName = selectedItem.Text;
+
+ MessageBox.Show("Delete " + itemName + " from " + selectedGroup.Name);
+ }
+
+
+
+ void editOption_Click(object sender, EventArgs e)
+ {
+ var menuItem = (ToolStripMenuItem)sender;
+ var menu = menuItem.Owner;
+ var selectedGroup = (ListGroup)menu.Tag;
+
+ // Only one selected item allowed for this demo:
+ var selectedItem = selectedGroup.SelectedItems[0];
+
+ string groupName = selectedGroup.Name;
+ string itemName = selectedItem.Text;
+
+ MessageBox.Show("Edit " + itemName + " from " + selectedGroup.Name);
+ }
+
+
+
+ void addOption_Click(object sender, EventArgs e)
+ {
+ var menuItem = (ToolStripMenuItem)sender;
+ var menu = menuItem.Owner;
+ var selectedGroup = (ListGroup)menu.Tag;
+
+ MessageBox.Show("Add a new item to " + selectedGroup.Name);
+ }
+
+
+ // Determine whether or not to use SingleItemOnly Expansion:
+ private void chkSingleItemOnlyMode_CheckedChanged(object sender, EventArgs e)
+ {
+ this.groupListControl1.SingleItemOnlyExpansion = this.chkSingleItemOnlyMode.Checked;
+ if (this.groupListControl1.SingleItemOnlyExpansion)
+ {
+ this.groupListControl1.CollapseAll();
+ }
+ else
+ {
+ this.groupListControl1.ExpandAll();
+ }
+ }
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+ foreach(ListGroup lg in this.groupListControl1.Controls)
+ {
+ lg.Columns.RemoveAt(lg.Columns.Count-1);
+ }
+ }
+
+ private void button2_Click(object sender, EventArgs e)
+ {
+ foreach (ListGroup lg in this.groupListControl1.Controls)
+ {
+ lg.Items.RemoveAt(lg.Items.Count - 1);
+ }
+ }
+
+
+
+
+
+ }
+}
120 GroupedListDemo/Form1.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
93 GroupedListDemo/GroupedListDemo.csproj
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{B90BCCEB-6690-44D2-94CC-8C16D1FC8EA6}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>GroupedListDemo</RootNamespace>
+ <AssemblyName>GroupedListDemo</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Deployment" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Form1.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="Form1.Designer.cs">
+ <DependentUpon>Form1.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <EmbeddedResource Include="Form1.resx">
+ <DependentUpon>Form1.cs</DependentUpon>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\GroupedListControl\GroupedListControl.csproj">
+ <Project>{2C43437C-5E27-48BE-BAC3-A3D0CDB30BFB}</Project>
+ <Name>GroupedListControl</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
21 GroupedListDemo/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace GroupedListDemo
+{
+ static class Program
+ {
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Form1());
+ }
+ }
+}
36 GroupedListDemo/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GroupedListDemo")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("GroupedListDemo")]
+[assembly: AssemblyCopyright("Copyright © 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("39ea67b3-01e3-437c-a088-a52283353288")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
71 GroupedListDemo/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.261
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace GroupedListDemo.Properties
+{
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GroupedListDemo.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
117 GroupedListDemo/Properties/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
30 GroupedListDemo/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.261
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace GroupedListDemo.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
7 GroupedListDemo/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
Please sign in to comment.
Something went wrong with that request. Please try again.