|
You just have to put it into the class which is inheriting from ListView (it's a normal method).
|
|
|
|
|
To make the sample work, add a class inheriting from ListView to the MainForm class in MainForm.cs. Then replace the two references to System.Windows.Forms.ListView in MainForm.Designer.cs with your extended class. For example, add the following as a nested class within MainForm
public class ExtListView : ListView
{
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x202:
base.DefWndProc(ref m);
base.WndProc(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
}
and then change
this.aoc = new System.Windows.Forms.ListView(); to
this.aoc = new ExtListView(); and
private System.Windows.Forms.ListView aoc; to
private ExtListView aoc; in the designer code.
|
|
|
|
|
It seems that it would be better to change WM_LBUTTONUP handler to the following one:
case WM_LBUTTONUP:
base.DefWndProc(ref m);
base.WndProc(ref m);
break;
Both DefWndProc and WndProc should be called. Otherwise either DoubleClick event may not be fired or collapse group arrow will not work... I have just run into this problem on Windows 8.
|
|
|
|
|
Thanks! Just had the exact same issue.
|
|
|
|
|
Hi sir! Good code, but why when I click the button from the group bar on each group bar, doesn't work? The button I mean, is located in the right of each ListViewGroup. Thanks!
|
|
|
|
|
Hello,
I am opening the MainForm of this Project from another Form called Form1 in the button click event.
For the first button click in Form1 i am able to collapse/expand Listview Groups, but for the next button clicks i'm unable to collapse/expand Listview Groups.
Please help me..
|
|
|
|
|
i encountered that too, but still now i dont have any idea how to fix it.. gush...
|
|
|
|
|
I downloaded the source code, Win 7, executed the project without changing anything and it throws an exception at the Marshl.StructureToPtr()
|
|
|
|
|
Sorry, I am running a 64-bit machine, just forced 32 bit and it worked.
|
|
|
|
|
Use this class for x86 and x64
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode), Description("LVGROUP StructureUsed to set and retrieve groups.")]
internal class LVGROUP
{
[Description("Size of this structure, in bytes.")]
public int CbSize = Marshal.SizeOf(typeof(LVGROUP));
[Description("Mask that specifies which members of the structure are valid input. One or more of the following values:LVGF_NONE No other items are valid.")]
public int Mask;
[Description("Pointer to a null-terminated string that contains the header text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the header text.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszHeader;
[Description("Size in TCHARs of the buffer pointed to by the pszHeader member. If the structure is not receiving information about a group, this member is ignored.")]
public int CchHeader;
[Description("Pointer to a null-terminated string that contains the footer text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the footer text.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszFooter;
[Description("Size in TCHARs of the buffer pointed to by the pszFooter member. If the structure is not receiving information about a group, this member is ignored.")]
public int CchFooter;
[Description("ID of the group.")]
public int IGroupId;
[Description("Mask used with LVM_GETGROUPINFO (Microsoft Windows XP and Windows Vista) and LVM_SETGROUPINFO (Windows Vista only) to specify which flags in the state value are being retrieved or set.")]
public int StateMask;
[Description("Flag that can have one of the following values:LVGS_NORMAL Groups are expanded, the group name is displayed, and all items in the group are displayed.")]
public int State;
[Description("Indicates the alignment of the header or footer text for the group. It can have one or more of the following values. Use one of the header flags. Footer flags are optional. Windows XP: Footer flags are reserved.LVGA_FOOTER_CENTERReserved.")]
public uint UAlign;
[Description("Windows Vista. Pointer to a null-terminated string that contains the subtitle text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subtitle text. This element is drawn under the header text.")]
public IntPtr PszSubtitle;
[Description("Windows Vista. Size, in TCHARs, of the buffer pointed to by the pszSubtitle member. If the structure is not receiving information about a group, this member is ignored.")]
public uint CchSubtitle;
[Description("Windows Vista. Pointer to a null-terminated string that contains the text for a task link when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the task text. This item is drawn right-aligned opposite the header text. When clicked by the user, the task link generates an LVN_LINKCLICK notification.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszTask;
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszTask member. If the structure is not receiving information about a group, this member is ignored.")]
public uint CchTask;
[Description("Windows Vista. Pointer to a null-terminated string that contains the top description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the top description text. This item is drawn opposite the title image when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszDescriptionTop;
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionTop member. If the structure is not receiving information about a group, this member is ignored.")]
public uint CchDescriptionTop;
[Description("Windows Vista. Pointer to a null-terminated string that contains the bottom description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the bottom description text. This item is drawn under the top description text when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszDescriptionBottom;
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionBottom member. If the structure is not receiving information about a group, this member is ignored.")]
public uint CchDescriptionBottom;
[Description("Windows Vista. Index of the title image in the control imagelist.")]
public int ITitleImage;
[Description("Windows Vista. Index of the extended image in the control imagelist.")]
public int IExtendedImage;
[Description("Windows Vista. Read-only.")]
public int IFirstItem;
[Description("Windows Vista. Read-only in non-owner data mode.")]
public IntPtr CItems;
[Description("Windows Vista. NULL if group is not a subset. Pointer to a null-terminated string that contains the subset title text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subset title text.")]
public IntPtr PszSubsetTitle;
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszSubsetTitle member. If the structure is not receiving information about a group, this member is ignored.")]
public IntPtr CchSubsetTitle;
public override string ToString()
{
return ("LVGROUP: header = " + this.PszHeader.ToString() + ", iGroupId = " + this.IGroupId.ToString(System.Globalization.CultureInfo.InvariantCulture));
}
}
|
|
|
|
|
|
Listview may get repaint issue when groups are collapsing or expanding with scrollbar presenting or disappearing. Tested on Win7.
A picture means everything.
http://hi.csdn.net/attachment/201105/27/1705918_1306468648h8Tc.jpg[^]
Follow up on 26/7/2011: API call SendMessage to force a redraw:
Public Property Let AllowRedraw(bRedraw As Boolean)
If m_hListView Then
Call SendMessage(m_hListView, WM_SETREDRAW, Abs(CLng(bRedraw)), 0&)
m_AllowRedraw = bRedraw
End If
End Property
modified on Tuesday, July 26, 2011 5:43 AM
|
|
|
|
|
I'd tried to do this exact same thing before, but never quite managed it. Your code showed me where I was going wrong. Cheers!
|
|
|
|
|
|
- The strings in LVGROUP should be LPWStr, not LPTStr. Check the windows headers.
- Why write your own marshaling code when you can just declare LVGROUP as ref param.
- Group id: someone else already mentioned it.
- Design: collapsible/collapsed should be properties of the group, as in win32 api. Yes, the group and group collection can't be inherited, but there're ways around it, and they can be added to work with the designer as if the properties come from the groups.
- Other misc stuffs like the use of const literals, exception handling...
All these are rather trivial, and that's why the article level is beginner.
|
|
|
|
|
In your "Design" issue you mention ways to add the functionality to the class and/or designer, could you point me in the direction of some information or examples on how this might be accomplished. Thanks.
|
|
|
|
|
Trivial stuff for Vista only...
|
|
|
|
|
I wouldn't say this is trivial. Not many people understand how to use interop code or even that you can use interop code to change the behavior of the standard .NET winforms controls.
List view grouping is also supported on Windows XP and later, including Vista and Win7. Being able to collapse the groups is Vista and later.
Scott Dorman Microsoft® MVP - Visual C# | MCPD
President - Tampa Bay IASA
[ Blog][ Articles][ Forum Guidelines] Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai
|
|
|
|
|
|
Thanks for this!
You can simplify this up and also make it an extension method:
public static int? GetID(this ListViewGroup lvg) =>
typeof(ListViewGroup).GetProperty("ID",
BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(lvg, null) as int?;
modified 10-Apr-20 12:44pm.
|
|
|
|
|
I would like to do this same thing for VB.Net...is there any way to do that?
Thanks in advance!
|
|
|
|
|
|
I had a similar problem while subclassing the listview control to catch LVN_LINKCLICK event. The fact is that ListView.WndProc catch the WM_LBUTTONUP event. So if you want to make it managed by the native control, you have to send it to DefWndProc first.
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
if(m.Msg == 0x202 /*WM_LBUTTONUP*/)
base.DefWndProc(ref m);
base.WndProc(ref m);
}
Regards,
François
|
|
|
|
|
For those wondering, here is the completed WndProc override to show the arrow and get the expand/collapse to work:
protected override void WndProc(ref Message m)
{
switch (m.Msg) {
case 0x1000 + 145:
// LVM_INSERTGROUP = LVM_FIRST + 145;
// Add the collapsible feature id needed
if (hasCollapsibleGroup) {
LVGROUP @group = (LVGROUP)Marshal.PtrToStructure(m.LParam, typeof(LVGROUP));
@group.state = (int)GroupState.COLLAPSIBLE;
// LVGS_COLLAPSIBLE
@group.mask = @group.mask ^ 4;
// LVGF_STATE
Marshal.StructureToPtr(@group, m.LParam, true);
}
base.WndProc(m);
break; // TODO: might not be correct. Was : Exit Select
break;
case 0x202:
//WM_LBUTTONUP
base.DefWndProc(m);
base.WndProc(m);
break; // TODO: might not be correct. Was : Exit Select
break;
default:
base.WndProc(m);
break; // TODO: might not be correct. Was : Exit Select
break;
}
}
However, I can't for the life of me figure out why I can't get the ExpandAll/Collapse all in this sample to work!!!!
It blows up on the following statement:
Marshal.StructureToPtr(@group, ip, true);
???????
The Doctor's In
Ron
|
|
|
|
|
what is hasCollapsibleGroup?
I don't see it set in your code, and in my version setting to either true or false i see no visible difference in the running.
|
|
|
|
|