在XP和Vista的Windows资源管理器中,当ListView处于“详细信息”模式时按列排序时,列的背景将突出显示以指示列正在排序。排序方向的箭头也显示在列标题中。在您自己的Windows窗体应用程序中实现这些效果的最佳实践是什么?
答案 0 :(得分:3)
此方法模拟“Windows XP”样式的选择。 Vista和Win7使用ListViews的扩展功能,但是.NET中没有(但是?)。如果需要,可以使用Interop完成。
以下是如何做到这一点:
创建一个包含以下图像的ImageList:0:空,1:“向上”和2:“向下”
在您刚刚添加的代码中,使用以下代码替换ColumnClick处理程序(此处的ListView实例称为“_List”):
void _List_ColumnClick(object sender,ColumnClickEventArgs e){ _List.SuspendLayout(); if(e.Column == lvwColumnSorter.SortColumn){//先前排序的列将被翻转 if(lvwColumnSorter.Order == SortOrder.Ascending){ lvwColumnSorter.Order = SortOrder.Descending; } else { lvwColumnSorter.Order = SortOrder.Ascending; } } else {//新列将被排序 _List.Columns [lvwColumnSorter.SortColumn] .ImageIndex = 0; foreach(_List.Items中的ListViewItem lvi){ lvi.SubItems [lvwColumnSorter.SortColumn] .BackColor = SystemColors.Window; } lvwColumnSorter.SortColumn = e.Column; lvwColumnSorter.Order = SortOrder.Ascending; } _List.Sort(); _List.Columns [e.Column] .ImageIndex = lvwColumnSorter.Order == SortOrder.Ascending? 1:2; foreach(_List.Items中的ListViewItem lvi){ lvi.SubItems [e.Column] .BackColor = SystemColors.Info; //这是用于跟踪的颜色 } _List.ResumeLayout(); }
编辑:
以下是互操作方法:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint message, UIntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint message, UIntPtr wParam, ref HDITEM lParam);
public enum WM {
LVM_FIRST = 0x1000, // ListView messages
// ...
LVM_GETHEADER = LVM_FIRST + 31,
// ...
HDM_FIRST = 0x1200, // Header messages
// ...
HDM_SETITEM = HDM_FIRST + 12,
// ...
HDM_SETFOCUSEDITEM = HDM_FIRST + 28,
}
public enum HDI {
HDI_WIDTH = 0x0001,
HDI_HEIGHT = HDI_WIDTH,
HDI_TEXT = 0x0002,
HDI_FORMAT = 0x0004,
HDI_LPARAM = 0x0008,
HDI_BITMAP = 0x0010,
HDI_IMAGE = 0x0020,
HDI_DI_SETITEM = 0x0040,
HDI_ORDER = 0x0080,
HDI_FILTER = 0x0100,
HDI_STATE = 0x0200
}
public enum HDF {
HDF_LEFT = 0x0000,
HDF_RIGHT = 0x0001,
HDF_CENTER = 0x0002,
HDF_JUSTIFYMASK = 0x0003,
HDF_RTLREADING = 0x0004,
HDF_BITMAP = 0x2000,
HDF_STRING = 0x4000,
HDF_OWNERDRAW = 0x8000,
HDF_IMAGE = 0x0800,
HDF_BITMAP_ON_RIGHT = 0x1000,
HDF_SORTUP = 0x0400,
HDF_SORTDOWN = 0x0200,
HDF_CHECKBOX = 0x0040,
HDF_CHECKED = 0x0080,
HDF_FIXEDWIDTH = 0x0100,
HDF_SPLITBUTTON = 0x1000000
}
[StructLayout(LayoutKind.Sequential)]
public struct HDITEM {
public uint mask;
public int cxy;
public String pszText;
public IntPtr hbm;
public int cchTextMax;
public int fmt;
public IntPtr lParam;
public int iImage;
public int iOrder;
public uint type;
public IntPtr pvFilter; // this is void*
public uint state;
}
void _List_ColumnClick(object sender, ColumnClickEventArgs e) {
_List.SuspendLayout();
HDITEM hdi = new HDITEM();
hdi.mask = (uint)HDI.HDI_FORMAT;
hdi.fmt = (int)HDF.HDF_STRING;
IntPtr hHeader = (IntPtr)SendMessage(_List.Handle, (uint)WM.LVM_GETHEADER, (UIntPtr)0, (IntPtr)0);
if (e.Column == lvwColumnSorter.SortColumn) { // the column previously sorted will be flipped
if (lvwColumnSorter.Order == SortOrder.Ascending) {
lvwColumnSorter.Order = SortOrder.Descending;
} else {
lvwColumnSorter.Order = SortOrder.Ascending;
}
} else { // new column will be sorted
SendMessage((IntPtr)hHeader, (uint)WM.HDM_SETITEM, (UIntPtr)lvwColumnSorter.SortColumn, ref hdi);
foreach (ListViewItem lvi in _List.Items) {
lvi.SubItems[lvwColumnSorter.SortColumn].BackColor = SystemColors.Window;
}
lvwColumnSorter.SortColumn = e.Column;
lvwColumnSorter.Order = SortOrder.Ascending;
}
_List.Sort();
hdi.fmt |= (lvwColumnSorter.Order == SortOrder.Ascending ? (int)HDF.HDF_SORTDOWN : (int)HDF.HDF_SORTUP);
SendMessage((IntPtr)hHeader, (uint)WM.HDM_SETITEM, (UIntPtr)e.Column, ref hdi);
foreach (ListViewItem lvi in _List.Items) {
lvi.SubItems[e.Column].BackColor = SystemColors.Info; // this is the color used for tracking
}
_List.ResumeLayout();
}