2011-07-03 69 views
14

Tôi muốn thay đổi chiều cao của Item/Row trong listview.C# Thay đổi ListView Chiều cao của Item/Row

Tôi đã tìm kiếm mọi nơi và tôi đã tìm ra rằng để thay đổi chiều cao, tôi cần sử dụng LBS_OWNERDRAWFIXED hoặc MeasureItem hoặc một cái gì đó tương tự.

Vấn đề là tôi không biết chính xác phải làm gì và cách sử dụng nó.
Có ai có thể giúp tôi không?

Edit:
I cant sử dụng ImageList Hack vì tôi đang sử dụng SmallImageList thật và tôi cần chiều cao dòng khác với kích thước hình ảnh ImageList.

Cảm ơn!

+0

Xem http://stackoverflow.com/questions/1244090/how-to-set-wpf-listview-row-height. Giải pháp đơn giản. –

+0

Các "giải pháp đơn giản" được đề cập là cho WPF - mà thực sự là đơn giản. Câu hỏi này liên quan đến WinForms - nơi nó được quyết định không đơn giản. – Grammarian

Trả lời

11

Nó có thể được thực hiện bằng cách sử dụng thủ thuật SmallImageList - bạn chỉ phải cẩn thận. ObjectListView - trình bao bọc mã nguồn mở xung quanh tiêu chuẩn .NET ListView - sử dụng mẹo đó để triển khai thành công thuộc tính RowHeight.

Nếu bạn muốn 32 pixel cho mỗi hàng, hãy phân bổ ImageList là 16x32 (chiều rộng x chiều cao) và sau đó định vị từng hình ảnh của bạn ở giữa chiều cao 32 pixel.

ảnh chụp màn hình này hiển thị các hàng 32-pixel và gói từ đó có thể do không gian thêm:

enter image description here

ObjectListView làm tất cả công việc này cho bạn. Trong thực tế, nếu bạn đang cố gắng làm bất cứ điều gì với một ListView, bạn nên nghiêm túc xem xét sử dụng một ObjectListView thay thế. Nó làm cho nhiều điều khó khăn (ví dụ: sắp xếp theo loại cột, chú giải công cụ tùy chỉnh) tầm thường và một số điều không thể (ví dụ: lớp phủ, nhóm trên danh sách ảo) có thể.

+1

Vâng, tôi chỉ muốn thay đổi kích thước hàng và 300kb cho điều đó là quá nhiều cho chương trình tôi dự định. anyway thats một giải pháp tốt nói chung. – Ron

+2

Tôi nghĩ bạn đã đề xuất một giải pháp rất phức tạp –

13

Bạn phải sử dụng một chút hack. Bí quyết là sử dụng một danh sách hình ảnh trong thuộc tính StateImageList. ListView sẽ điều chỉnh chiều cao mục của nó, dựa trên chiều cao của thuộc tính ImageSize của ImageList. Bạn không phải chỉ định một hình ảnh cho các mục của bạn, nhưng chỉ cần sử dụng StateImageList sẽ buộc ListView điều chỉnh. Trong ví dụ dưới đây, tôi đã đặt kích thước danh sách hình ảnh thành 32x32, do đó tạo ra một ListViewItem có chiều cao 32px.

enter image description here

+1

Tôi quên nói, tôi đang sử dụng ImageList trong SmallImageList proeprty vì vậy tôi không thể sử dụng hack đó. – Ron

+0

Sau đó, bạn sẽ phải viết kiểm soát của riêng bạn, bởi vì từ kinh nghiệm và nghiên cứu, điều này sẽ không thể thực hiện được với ListView WinForms hiện có. Đây cũng là câu trả lời tương tự từ một nhà phát triển Hỗ trợ Cộng đồng MSFT, người cũng đã nghiên cứu vấn đề cho một số người, và nó kết thúc bằng việc đề xuất viết một điều khiển tùy chỉnh. –

+0

Tôi đã thử nghiệm chế độ này chi tiết. Thủ thuật này chỉ hoạt động để TĂNG chiều cao hàng trên chiều cao defaut. Bạn không thể làm cho các hàng chặt hơn Windows xác định. Xin lưu ý chiều cao của hàng listview phụ thuộc vào hệ điều hành. Ví dụ trên Windows 7 hàng cao hơn đáng kể so với XP. Đáng buồn thay lừa này không phải là hữu ích cho tôi. – Elmue

1

Chiều cao dòng mặc định của một ListView (trong chế độ xem báo cáo) được tính toán dựa trên kích thước phông chữ của kiểm soát.

Vì vậy, để chọn chiều cao dòng, hãy chọn phông chữ có chiều cao phù hợp trong thuộc tính ListView. Ví dụ: chọn MS Sans Serif 18.

Sau đó, bạn có thể thay đổi phông chữ được sử dụng bởi tất cả các mục: khi bạn chèn một mục mới, đặt thuộc tính phông chữ của nó.

Để tối ưu hóa phân font bạn nên khai báo font mục như một thành viên tư nhân có dạng:

Private Font stdfont = new Font("Consolas", 9.0f, FontStyle.Regular); 

Sau đó, khi thêm các mục:

ListViewItem i = new ListViewItem("some text"); 
i.Font = stdfont; 
MyListView.Items.Add(i); 

lừa Đây là một dễ dàng chỉ cho phép để có chiều cao dòng SMALLER;) iE thiết lập font size kiểm soát thành 7 và thiết lập font size mục đến 10 (Tested với VS 2008)

11

Đối với những người mà vẫn đang strugling với điều này, đây là đoạn code tôi sử dụng:

private void SetHeight(ListView listView, int height) 
{ 
    ImageList imgList = new ImageList(); 
    imgList.ImageSize = new Size(1, height); 
    listView.SmallImageList = imgList; 
} 

Để sử dụng điều này chỉ cần thực hiện:

SetHeight(lvConnections, 25); 
+0

Tôi đã thử nghiệm chế độ này chi tiết. Thủ thuật này chỉ hoạt động để TĂNG chiều cao hàng trên chiều cao defaut. Bạn không thể làm cho các hàng chặt hơn Windows xác định. Xin lưu ý chiều cao của hàng listview phụ thuộc vào hệ điều hành. Ví dụ trên Windows 7 hàng cao hơn đáng kể so với XP. Đáng buồn thay lừa này không phải là hữu ích cho tôi. – Elmue

0

Plasmabubble có ý tưởng đúng. Điều này mở rộng trên đó và là những gì tôi sử dụng để sử dụng một chiều rộng dòng hẹp cho các mục.

Đường kẻ trong ListView phụ thuộc vào phông chữ của ListView và không thể thay đổi. Tuy nhiên, bạn có thể đặt phông chữ cho các mục trong ListView thành một cái gì đó lớn hơn phông chữ của ListView.

Nếu bạn muốn tỷ lệ thuận, hãy tạo phông chữ dựa trên phông chữ của mục. Tôi muốn chiều cao mục là 90% bình thường, bất kể phông chữ được chọn.

Khi tôi điền danh sách, tôi đã sử dụng phông chữ được lưu trữ trong cài đặt nhưng bạn cũng có thể sử dụng phông chữ như "Consolas".

lvResults.Font = 
    new Font(Properties.Settings.Default.usrHookFont.FontFamily, 
     (float)(Properties.Settings.Default.usrHookFont.Size * .9)); 

foreach (HookSet item in resultSet) 
    { 
     ListViewItem lvi = new ListViewItem(); 
     lvi.Font = Properties.Settings.Default.usrHookFont; 
     <dot><dot><dot> 
} 
0

Rất tiếc, không ai trả lời câu hỏi ban đầu của bạn về cách sử dụng LBS_OWNERDRAWFIXED trong tất cả các năm này.

Câu trả lời mà bạn đã chấp nhận là tích hợp một dự án lớn (với bản trình diễn và tài liệu 3,3MB). Nhưng chỉ để thiết lập chiều cao dòng của một ListView này là overbloated.

Cách giải quyết khác được đề xuất ở đây (thêm Danh sách hình ảnh) chỉ hoạt động để tăng chiều cao hàng. Nhưng nó không cho phép thực sự thiết lập RowHeight độc lập với chiều cao hình ảnh. Ngoài ra chiều cao hàng mặc định phụ thuộc vào hệ điều hành. Ví dụ trên Windows 7, các hàng cao hơn nhiều so với XP. Bạn không thể chọn làm cho chúng chặt hơn, chỉ cao hơn.

Nhưng với rất ít dòng, bạn có thể làm những gì bạn muốn. Chỉ cần sao chép và dán lớp sau đây:

using System; 
using System.Drawing; 
using System.Diagnostics; 
using System.ComponentModel; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 

namespace ExtendedControls 
{ 

public class ListViewEx : ListView 
{ 
    #region Windows API 

    /* 
    struct MEASUREITEMSTRUCT 
    { 
     public int CtlType;  // Offset = 0 
     public int CtlID;  // Offset = 1 
     public int itemID;  // Offset = 2 
     public int itemWidth; // Offset = 3 
     public int itemHeight; // Offset = 4 
     public IntPtr itemData; 
    } 
    */ 

    [StructLayout(LayoutKind.Sequential)] 
    struct DRAWITEMSTRUCT 
    { 
     public int ctlType; 
     public int ctlID; 
     public int itemID; 
     public int itemAction; 
     public int itemState; 
     public IntPtr hWndItem; 
     public IntPtr hDC; 
     public int rcLeft; 
     public int rcTop; 
     public int rcRight; 
     public int rcBottom; 
     public IntPtr itemData; 
    } 

    // LVS_OWNERDRAWFIXED: The owner window can paint ListView items in report view. 
    // The ListView control sends a WM_DRAWITEM message to paint each item. It does not send separate messages for each subitem. 
    const int LVS_OWNERDRAWFIXED = 0x0400; 
    const int WM_SHOWWINDOW  = 0x0018; 
    const int WM_DRAWITEM  = 0x002B; 
    const int WM_MEASUREITEM  = 0x002C; 
    const int WM_REFLECT   = 0x2000; 

    #endregion 

    bool mb_Measured = false; 
    int ms32_RowHeight = 14; 

    /// <summary> 
    /// Constructor 
    /// </summary> 
    public ListViewEx() 
    { 
     SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); 
    } 

    /// <summary> 
    /// Sets the row height in Details view 
    /// This property appears in the Visual Studio Form Designer 
    /// </summary> 
    [Category("Appearance")] 
    [Description("Sets the height of the ListView rows in Details view in pixels.")] 
    public int RowHeight 
    { 
     get { return ms32_RowHeight; } 
     set 
     { 
      if (!DesignMode) Debug.Assert(mb_Measured == false, "RowHeight must be set before ListViewEx is created."); 
      ms32_RowHeight = value; 
     } 
    } 

    protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams k_Params = base.CreateParams; 
      k_Params.Style |= LVS_OWNERDRAWFIXED; 
      return k_Params; 
     } 
    } 

    /// <summary> 
    /// The messages WM_MEASUREITEM and WM_DRAWITEM are sent to the parent control rather than to the ListView itself. 
    /// They come here as WM_REFLECT + WM_MEASUREITEM and WM_REFLECT + WM_DRAWITEM 
    /// They are sent from Control.WmOwnerDraw() --> Control.ReflectMessageInternal() 
    /// </summary> 
    protected override void WndProc(ref Message k_Msg) 
    { 
     base.WndProc(ref k_Msg); // FIRST 

     switch (k_Msg.Msg) 
     { 
      case WM_SHOWWINDOW: // called when the ListView becomes visible 
      { 
       Debug.Assert(View == View.Details, "ListViewEx supports only Details view"); 
       Debug.Assert(OwnerDraw == false, "In ListViewEx do not set OwnerDraw = true"); 
       break; 
      } 
      case WM_REFLECT + WM_MEASUREITEM: // called once when the ListView is created, but only in Details view 
      { 
       mb_Measured = true; 

       // Overwrite itemHeight, which is the fifth integer in MEASUREITEMSTRUCT 
       Marshal.WriteInt32(k_Msg.LParam + 4 * sizeof(int), ms32_RowHeight); 
       k_Msg.Result = (IntPtr)1; 
       break; 
      } 
      case WM_REFLECT + WM_DRAWITEM: // called for each ListViewItem to be drawn 
      { 
       DRAWITEMSTRUCT k_Draw = (DRAWITEMSTRUCT) k_Msg.GetLParam(typeof(DRAWITEMSTRUCT)); 
       using (Graphics i_Graph = Graphics.FromHdc(k_Draw.hDC)) 
       { 
        ListViewItem i_Item = Items[k_Draw.itemID]; 

        Color c_BackColor = i_Item.BackColor; 
        if (i_Item.Selected) c_BackColor = SystemColors.Highlight; 
        if (!Enabled)  c_BackColor = SystemColors.Control; 

        using (SolidBrush i_BackBrush = new SolidBrush(c_BackColor)) 
        { 
         // Erase the background of the entire row 
         i_Graph.FillRectangle(i_BackBrush, i_Item.Bounds); 
        } 

        for (int S=0; S<i_Item.SubItems.Count; S++) 
        { 
         ListViewItem.ListViewSubItem i_SubItem = i_Item.SubItems[S]; 

         // i_Item.SubItems[0].Bounds contains the entire row, rather than the first column only. 
         Rectangle k_Bounds = (S>0) ? i_SubItem.Bounds : i_Item.GetBounds(ItemBoundsPortion.Label); 

         // You can use i_Item.ForeColor instead of i_SubItem.ForeColor to get the same behaviour as without OwnerDraw 
         Color c_ForeColor = i_SubItem.ForeColor; 
         if (i_Item.Selected) c_ForeColor = SystemColors.HighlightText; 
         if (!Enabled)  c_ForeColor = SystemColors.ControlText; 

         TextFormatFlags e_Flags = TextFormatFlags.NoPrefix | TextFormatFlags.EndEllipsis | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine; 
         switch (Columns[S].TextAlign) 
         { 
          case HorizontalAlignment.Center: e_Flags |= TextFormatFlags.HorizontalCenter; break; 
          case HorizontalAlignment.Right: e_Flags |= TextFormatFlags.Right; break; 
         } 

         TextRenderer.DrawText(i_Graph, i_SubItem.Text, i_SubItem.Font, k_Bounds, c_ForeColor, e_Flags); 
        } 
       } 
       break; 
      } 
     } 
    } 
} // class 
} // namespace 

Sau khi thêm một ListViewEx Mẫu của bạn, bạn sẽ thấy một đặc tính mới trong Visual Forms Studio thiết kế cho phép để thiết lập chiều cao hàng bằng pixel:

Setting RowHeight in a C# ListView

Giá trị bạn nhập ở đó sẽ có chiều cao hàng tính bằng pixel và nó sẽ được tôn trọng một cách ngoại lệ trên tất cả các hệ điều hành.Tôi đã thử nghiệm nó trên Windows XP, 7 và 10:

ListViewEx.RowHeight sample

Ngoài lớp học của tôi có hai ưu điểm hơn so với ListView gốc: Nó dựa flicker-free và nó tôn trọng ForeColorFont đặt trong ListViewSubItem được bỏ qua bởi Microsoft ListView gốc. Vì vậy, bạn có thể vẽ từng ô bằng màu và phông chữ khác nhau.

QUAN TRỌNG: Khi MSDN nói LBS_OWNERDRAWFIXED đã được thiết kế chỉ cho thị chi tiết Hiển (Báo cáo xem). Mã của tôi chỉ hoạt động cho chế độ này và điều này là do Microsoft đã thiết kế nó như thế.

Ngoài ra, xin lưu ý rằng thiết lập ListView.OwnerDraw = true là một điều hoàn toàn khác với việc sử dụng LVS_OWNERDRAWFIXED.

Tôi không triển khai vẽ các biểu tượng, bởi vì tôi không cần điều đó. Nhưng bạn có thể dễ dàng thêm điều này.

+0

Ghi đè CreateParams đang khiến văn bản phụ không hiển thị ... – user1932634

+0

Tôi hoàn toàn không biết bạn đang nói về điều gì. Tôi sử dụng mã này trong ứng dụng của mình. Nó hoạt động hoàn hảo! Trong các ảnh chụp màn hình ở trên, bạn thấy rằng tất cả các phần phụ được vẽ chính xác, ngay cả trong màu sắc. – Elmue

Các vấn đề liên quan