none
为什么这个函数不能使 ListView 显示排序箭头? RRS feed

  • 问题

  • const Int32 HDF_SORTDOWN = 0x200;
    const Int32 HDF_SORTUP = 0x400;
    const Int32 HDI_FORMAT = 0x4;
    const Int32 HDM_GETITEM = 0x120b;
    const Int32 HDM_SETITEM = 0x120c;
    const Int32 LVM_GETHEADER = 0x101f;
    
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam);
    
    [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
    static extern IntPtr SendMessageLVCOLUMN(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref LVCOLUMN lParam);
    
    struct LVCOLUMN
    {
      public UInt32 mask;
      public Int32 fmt;
      public Int32 cx;
      public String pszText;
      public Int32 cchTextMax;
      public Int32 iSubItem;
      public Int32 iImage;
      public Int32 iOrder;
      public Int32 cxMin;
      public Int32 cxDefault;
      public Int32 cxIdeal;
    }
    
    private void SetSortIcon(ListView lstVw, int column, SortOrder sorting)
    {
      IntPtr clmHdr = SendMessage(lstVw.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
    
      for (int i = 0; i < lstVw.Columns.Count; i++)
      {
        IntPtr clmPtr = new IntPtr(i);
        LVCOLUMN lvColumn = new LVCOLUMN();
    
        lvColumn.mask = HDI_FORMAT;
        SendMessageLVCOLUMN(clmHdr, HDM_GETITEM, clmPtr, ref lvColumn);
        if (sorting != SortOrder.None && i == column)
        {
          if (sorting == SortOrder.Ascending)
          {
            lvColumn.fmt &= ~HDF_SORTDOWN;
            lvColumn.fmt |= HDF_SORTUP;
          }
          else
          {
            lvColumn.fmt &= ~HDF_SORTUP;
            lvColumn.fmt |= HDF_SORTDOWN;
          }
        }
        else
        {
          lvColumn.fmt &= ~HDF_SORTDOWN & ~HDF_SORTUP;
        }
        SendMessageLVCOLUMN(clmHdr, HDM_SETITEM, clmPtr, ref lvColumn);
      }
    }
    

    然后执行

    SetSortIcon(lstVwMain, 0, SortOrder.Ascending);
    
    为什么没有效果?


    EFanZh
    2011年6月7日 5:04

答案

全部回复

  • 您好,

    你的意思是让listview在排序之后出现向上或者向下的箭头嘛?

    我想如果这样的话, 你可以想将向上和向下箭头的图片加到ImageList中,然后用如下代码进行赋值。

     

    this.listView1.Columns[columnIndex].ImageIndex = imageindex;

     


    Vin Jin [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已建议为答案 Charles Shao 2011年6月9日 1:28
    • 取消建议作为答案 EFanZh 2011年6月11日 13:32
    2011年6月8日 6:19
  • 我希望用系统定义的箭头。

    LS 说的这种方法我知道,不过这不是我想要的。

    上面的代码,如果是扩展方法了的话就能产生效果。

    即:

    public static class ListViewExtensions
    {
      const Int32 HDF_SORTDOWN = 0x200;
      const Int32 HDF_SORTUP = 0x400;
      const Int32 HDI_FORMAT = 0x4;
      const Int32 HDM_GETITEM = 0x120b;
      const Int32 HDM_SETITEM = 0x120c;
      const Int32 LVM_GETHEADER = 0x101f;
    
      private struct LVCOLUMN
      {
        public Int32 mask;
        public Int32 cx;
        public String pszText;
        public IntPtr hbm;
        public Int32 cchTextMax;
        public Int32 fmt;
        public Int32 iSubItem;
        public Int32 iImage;
        public Int32 iOrder;
      }
    
      [DllImport("user32.dll")]
      private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam);
    
      [DllImport("user32.dll", EntryPoint = "SendMessage")]
      private static extern IntPtr SendMessageLVCOLUMN(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref LVCOLUMN lParam);
    
      public static void SetSortIcon(this ListView lstVw, int column, SortOrder sorting)
      {
        IntPtr clmHdr = SendMessage(lstVw.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
    
        for (int i = 0; i < lstVw.Columns.Count; i++)
        {
          IntPtr clmPtr = new IntPtr(i);
          LVCOLUMN lvColumn = new LVCOLUMN();
    
          lvColumn.mask = HDI_FORMAT;
          SendMessageLVCOLUMN(clmHdr, HDM_GETITEM, clmPtr, ref lvColumn);
          if (sorting != SortOrder.None && i == column)
          {
            if (sorting == SortOrder.Ascending)
            {
              lvColumn.fmt &= ~HDF_SORTDOWN;
              lvColumn.fmt |= HDF_SORTUP;
            }
            else
            {
              lvColumn.fmt &= ~HDF_SORTUP;
              lvColumn.fmt |= HDF_SORTDOWN;
            }
          }
          else
          {
            lvColumn.fmt &= ~HDF_SORTDOWN & ~HDF_SORTUP;
          }
          SendMessageLVCOLUMN(clmHdr, HDM_SETITEM, clmPtr, ref lvColumn);
        }
      }
    }
    

    这样就可以。

    可为什么第一种方法无效?


    EFanZh
    • 已建议为答案 Charles Shao 2011年6月9日 1:28
    • 取消建议作为答案 EFanZh 2011年6月11日 13:32
    2011年6月8日 18:01
  • 哇,学习了! 不过我还是比较赞成Vin Jin的做法。 毕竟如果客户没有要求的话,以最快的速度和最简便的代码实现是首选的。不要老跟自己过不去。

    所谓的精益求精是要花在用户体验和效率算法上的,而不是这种地方。。。呵呵  个人看法而已,仅供参考


    信奎爷,无所畏惧!!
    • 已建议为答案 Charles Shao 2011年6月9日 1:31
    • 取消建议作为答案 EFanZh 2011年6月11日 13:32
    2011年6月9日 1:31
  • 自己学习的,不是给别人做东西。

    兴趣而已,想了解更多的东西。

    大家最好能试验一下第二种方法,然后尝试改成非扩展方法,再看看是否有效。

    我只是很好奇为什么无效罢了。纯学习目的。

    Thanks.

     


    EFanZh
    2011年6月9日 6:34
  • 这个问题我觉得很有问题。

    你写的这个方法我想只能在扩展方法中才能实现你想要的做法。因为你这个方法本来就是这样。这就好比你问问什么我写的一个程序能在XP下运行却不能在WIN7 下运行一样。

    我看了你的代码,你这个应该是在网上找的吧。网上用这个来实现排序箭头都是用扩展方法, 也就是你的第2中方法。所以说人家提供的solution本来就是在作为扩展方法的前提下才能够正常运行。

    首先你要了解什么是扩展方法和普通方法的区别。http://msdn.microsoft.com/zh-cn/library/bb383977.aspx

    如果你要实现第一种, 我想你需要修改代码来实现。因为这个代码只适合在扩展方法的前提下才能实现效果。


    Please Mark it as answer, if it helps solve your problem.
    2011年6月12日 4:33
  • 那么,如何修改代码才能使用非扩展方法实现呢?

    或者,非扩展方法是不能实现的?


    EFanZh
    2011年6月13日 4:37
  • 最简单的就是按照版主提供的方法。

    如果你要自己去实现而不用现成那就有点多此一举了。而且你需要自己去写代码来满足自己的需求。


    Please Mark it as answer, if it helps solve your problem.
    • 已标记为答案 EFanZh 2011年6月13日 7:15
    • 取消答案标记 EFanZh 2011年6月14日 11:59
    2011年6月13日 5:24
  • 就这样吧。

    不过还是没解决我的问题。

    不管怎么样还是谢了。


    EFanZh
    2011年6月13日 7:15
  • 我找到答案了。

    我的 LVCOLUMN 结构是错误的。

    应该是

    private struct LVCOLUMN
    {
      public Int32 mask;
      public Int32 cx;
      public String pszText;
      public IntPtr hbm;
      public Int32 cchTextMax;
      public Int32 fmt;
      public Int32 iSubItem;
      public Int32 iImage;
      public Int32 iOrder;
    }
    


    StackOverFlow 帮忙解决的:

    http://stackoverflow.com/questions/6342340/why-this-method-doesnt-work


    EFanZh
    • 已标记为答案 EFanZh 2011年6月14日 11:58
    2011年6月14日 11:58