2011-07-03 29 views
14

Chcę zmienić wysokość elementu/wiersza w widoku listy.C# Zmień listę Wyświetl wysokość elementu/wiersza

Przeszukałem wszystkie miejsca i doszedłem do wniosku, że aby zmienić wysokość, muszę użyć LBS_OWNERDRAWFIXED lub MeasureItem lub coś w tym stylu.

Problem polega na tym, że nie wiem dokładnie, co robić i jak z niego korzystać.
Czy ktoś może mi w tym pomóc?

Edit:
nie mogę używać hack ImageList ponieważ używam SmallImageList za prawdziwe i muszę różną wysokość abonamentu od rozmiaru zdjęć Imagelist.

Dzięki!

+0

Zobacz http://stackoverflow.com/questions/1244090/how-to-set-wpf-listview-row-height. Proste rozwiązanie. –

+0

Wspomniane "proste rozwiązanie" dotyczy WPF - co jest naprawdę proste. To pytanie dotyczy WinForms - gdzie nie jest to proste. – Grammarian

Odpowiedz

11

Można to zrobić za pomocą SmallImageList sztuczkę - po prostu trzeba być ostrożnym. ObjectListView - Otoczka open source wokół standardowego .NET ListView - wykorzystuje tę sztuczkę do pomyślnego wdrożenia właściwości RowHeight.

Jeśli chcesz 32 pikseli dla każdego wiersza, przydziel ImageList, czyli 16x32 (szerokość x wysokość), a następnie umieść każde ze zdjęć w pionowym środku 32-pikselowego poziomu.

Ten zrzut ekranu pokazuje wiersze 32-pikselowych i zawijanie że jest to możliwe ze względu na dodatkową przestrzeń:

enter image description here

ObjectListView to wszystko za Ciebie. W rzeczywistości, jeśli próbujesz zrobić cokolwiek z ListView, powinieneś poważnie spojrzeć na użycie zamiast tego ObjectListView. Sprawia, że ​​wiele trudnych rzeczy (np. Sortowanie według typu kolumny, niestandardowych podpowiedzi) jest banalnie proste, a kilka niemożliwych rzeczy (np. Nakładki, grupy na wirtualnych listach) jest możliwe.

+1

Po prostu chciałem zmienić rozmiar wiersza i 300kb, ponieważ to zbyt dużo dla programu, który planuję. w każdym razie to dobre rozwiązanie w ogóle. – Ron

+2

Myślę, że zaproponowałeś rozwiązanie tak złożone –

13

Musisz użyć trochę hackowania. Sztuką jest użycie listy obrazów w właściwości StateImageList. ListView dostosuje wysokość elementu w oparciu o wysokość właściwości ImageSize ImageLista. Nie musisz podawać obrazu dla swoich przedmiotów, ale użycie StateImageList zmusi ListView do dostosowania. W poniższym przykładzie ustawiłem rozmiar listy obrazów na 32x32, uzyskując w ten sposób wysokość ListViewItem o wysokości 32 pikseli.

enter image description here

+1

Zapomniałem powiedzieć, używam ImageList w ProImprty SmallImageList, więc nie mogę użyć tego hack. – Ron

+0

Następnie musisz napisać własną kontrolę, ponieważ z doświadczenia i badań nie będzie to możliwe z istniejącym ListView WinForm. To była również ta sama odpowiedź ze strony działu wsparcia społecznościowego MSFT, który również zbadał problem dla niektórych osób, a ostatecznie zasugerował napisanie niestandardowej kontroli. –

+0

Przetestowałem to w trybie szczegółowym. Ta sztuczka działa tylko w celu zwiększenia wysokości wiersza nad wysokością defautu. Nie można tworzyć rzędów mocniej niż definiuje system Windows. Zwróć uwagę, że wysokość wiersza widoku listy zależy od systemu operacyjnego. Na przykład w Windows 7 wiersze są znacznie wyższe niż w XP. Niestety ta sztuczka nie jest dla mnie przydatna. – Elmue

1

Domyślna wysokość linii ListView (w trybie widoku raportu) jest obliczana na podstawie rozmiaru czcionki kontrolnej.

Aby wybrać wysokość linii, wybierz czcionkę o odpowiedniej wysokości we właściwościach ListView. Na przykład wybierz MS Sans Serif 18.

Następnie możesz zmienić czcionkę używaną przez wszystkie elementy: po wstawieniu nowego elementu, ustaw jego właściwość font.

Aby zoptymalizować przypisania czcionek należy zadeklarować czcionkę artykuł jako prywatny członek postaci:

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

Następnie podczas dodawania pozycji:

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

Ta sztuczka jest tylko łatwa pozwalający mieć MNIEJSZĄ wysokość linii;) iE ustawić rozmiar czcionki formantu do 7 i ustawić rozmiar czcionki aplikacji na 10. (Testowane z VS 2008)

11

dla osób, które są nadal strugling z tym, tu jest kod używam:

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

Aby użyć tego po prostu wykonaj:

SetHeight(lvConnections, 25); 
+0

Przetestowałem to w trybie szczegółowym. Ta sztuczka działa tylko w celu zwiększenia wysokości wiersza nad wysokością defautu. Nie można tworzyć rzędów mocniej niż definiuje system Windows. Zwróć uwagę, że wysokość wiersza widoku listy zależy od systemu operacyjnego. Na przykład w Windows 7 wiersze są znacznie wyższe niż w XP. Niestety ta sztuczka nie jest dla mnie przydatna. – Elmue

0

Plasmabubble ma dobry pomysł. Rozwija się to i jest tym, czego używam do wąskiej szerokości linii dla przedmiotów.

Przełożenie linii w widoku listy jest zależne od czcionki ListView i nie można go zmienić. Jednak możesz ustawić czcionkę dla elementów w ListView na coś większego niż czcionka ListView.

Jeśli chcesz, aby był proporcjonalny, utwórz czcionkę w oparciu o czcionkę przedmiotu. Chcę, aby wysokość elementu wynosiła 90% wartości normalnej, bez względu na wybraną czcionkę.

Po zapełnieniu listy użyłem czcionki zapisanej w ustawieniach, ale można również użyć literalnej czcionki, np. "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

Niestety nikt nie odpowiedział na oryginalne pytanie, jak używać LBS_OWNERDRAWFIXED w tych wszystkich latach.

Odpowiedź, którą zaakceptowałeś, polega na integracji dużego projektu (z wersjami demonstracyjnymi i dokumentacją 3,3 MB). Ale tylko dla ustawienia wysokości linii ListView jest to przesadne.

Inne sugerowane tutaj obejście (dodanie elementu ImageList) działa tylko pod warunkiem, że zwiększy wysokość wiersza o. Nie pozwala jednak na ustawienie wysokości RowHeight niezależnie od wysokości obrazu. Dodatkowo domyślna wysokość wiersza zależy od systemu operacyjnego. Na przykład w Windows 7 wiersze są znacznie wyższe niż w XP. Nie możesz zdecydować, aby były mocniejsze, tylko wyższe.

Ale przy niewielu liniach możesz robić, co chcesz. Po prostu skopiuj i wklej następujące klasy:

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 

Po dodaniu ListViewEx do formularza będzie można zobaczyć nową właściwość w Visual Form Studio Designer, który pozwala ustawić wysokość wiersza w pikselach:

Setting RowHeight in a C# ListView

Wartość, którą tam wprowadzisz, będzie wysokością wiersza w pikselach i będzie przestrzegana exatctly we wszystkich systemach operacyjnych.Testowałem go na Windows XP, 7 i 10:

ListViewEx.RowHeight sample

Dodatkowo moja klasa ma jeszcze dwie zalety w stosunku do oryginalnego ListView: Zwraca niemigoczący i szanuje ForeColor i czcionki ustawiony w ListViewSubItem, który jest ignorowany przez oryginalny ListView Microsoft. Możesz więc rysować każdą komórkę innym kolorem i czcionką.

WAŻNE: Jako MSDN mówi LBS_OWNERDRAWFIXED został zaprojektowany tylko dla Szczegóły widzenia (-aś). Mój kod działa tylko w tym trybie, a to dlatego, że Microsoft tak to zaprojektował.

Dodatkowo należy pamiętać, że ustawienie ListView.OwnerDraw = true jest zupełnie inne niż użycie LVS_OWNERDRAWFIXED.

Nie wdrożyłem rysunku ikony, ponieważ nie potrzebuję tego. Ale możesz to łatwo dodać.

+0

Przesłonięcie CreateParams powoduje, że tekst w podmiocie nie jest wyświetlany ... – user1932634

+0

Nie mam absolutnie pojęcia, o czym mówisz. Używam tego kodu w mojej aplikacji. Działa doskonale! Na powyższych zrzutach ekranu widać, że wszystkie elementy podrzędne są rysowane prawidłowo, nawet w kolorze. – Elmue