Не удается получить элементы и столбцы для отображения listview
На данный момент я получаю listview, чтобы появиться, однако, ничего не появляется в listview. Это странно, потому что я могу видеть элементы и столбцы, отображаемые в предварительном запуске listview. После того, как программа работает в ListView остается пустым.
Вот код, который я использую:
Вот элемент управления listview, который создается:
Imports System Imports System.Collections Imports System.ComponentModel Imports System.Drawing Imports System.Windows.Forms Imports System.Runtime.InteropServices Namespace ListViewEmbeddedControls Public Class ListViewEx Inherits ListView <DllImport("user32.dll")> Private Shared Function SendMessage(hWnd As IntPtr, msg As Integer, wPar As IntPtr, lPar As IntPtr) As IntPtr End Function Private Const LVM_FIRST As Integer = &H1000 Private Const LVM_GETCOLUMNORDERARRAY As Integer = (LVM_FIRST + 59) Private Const WM_PAINT As Integer = &HF Private Structure EmbeddedControl Public Control As Control Public Column As Integer Public Row As Integer Public Dock As DockStyle Public Item As ListViewItem End Structure Private _embeddedControls As New ArrayList() Protected Function GetColumnOrder() As Integer() Dim lPar As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(Integer)) * Columns.Count) Dim res As IntPtr = SendMessage(Handle, LVM_GETCOLUMNORDERARRAY, New IntPtr(Columns.Count), lPar) If res.ToInt32() = 0 Then Marshal.FreeHGlobal(lPar) Return Nothing End If Dim order As Integer() = New Integer(Columns.Count) {} Marshal.Copy(lPar, order, 0, Columns.Count) Marshal.FreeHGlobal(lPar) Return order End Function Protected Function GetSubItemBounds(Item As ListViewItem, SubItem As Integer) As Rectangle Dim subItemRect As Rectangle = Rectangle.Empty If Item Is Nothing Then Throw New ArgumentNullException("Item") End If Dim order As Integer() = GetColumnOrder() If order Is Nothing Then Return subItemRect End If If SubItem >= order.Length Then Throw New IndexOutOfRangeException("SubItem " + SubItem + " out of range") End If Dim lviBounds As Rectangle = Item.GetBounds(ItemBoundsPortion.Entire) Dim subItemX As Integer = lviBounds.Left Dim col As ColumnHeader Dim i As Integer i = 0 While i < order.Length col = Me.Columns(order(i)) If col.Index = SubItem Then Exit While End If subItemX += col.Width System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1) End While subItemRect = New Rectangle(subItemX, lviBounds.Top, Me.Columns(order(i)).Width, lviBounds.Height) Return subItemRect End Function Public Sub AddEmbeddedControl(c As Control, col As Integer, row As Integer) AddEmbeddedControl(c, col, row, DockStyle.Fill) End Sub Public Sub AddEmbeddedControl(c As Control, col As Integer, row As Integer, dock As DockStyle) If c Is Nothing Then Throw New ArgumentNullException() End If If col >= Columns.Count OrElse row >= Items.Count Then Throw New ArgumentOutOfRangeException() End If Dim ec As EmbeddedControl ec.Control = c ec.Column = col ec.Row = row ec.Dock = dock ec.Item = Items(row) _embeddedControls.Add(ec) Me.Controls.Add(c) End Sub Public Function GetEmbeddedControl(col As Integer, row As Integer) As Control For Each ec As EmbeddedControl In _embeddedControls If ec.Row = row AndAlso ec.Column = col Then Return ec.Control End If Next Return Nothing End Function Protected Overloads Overrides Sub WndProc(ByRef m As Message) Select Case m.Msg Case WM_PAINT If View <> View.Details Then Exit Select End If For Each ec As EmbeddedControl In _embeddedControls Dim rc As Rectangle = Me.GetSubItemBounds(ec.Item, ec.Column) If (Me.HeaderStyle <> ColumnHeaderStyle.None) AndAlso (rc.Top < Me.Font.Height) Then ec.Control.Visible = False Continue For Else ec.Control.Visible = True End If Select Case ec.Dock Case DockStyle.Fill Exit Select Case DockStyle.Top rc.Height = ec.Control.Height Exit Select Case DockStyle.Left rc.Width = ec.Control.Width Exit Select Case DockStyle.Bottom rc.Offset(0, rc.Height - ec.Control.Height) rc.Height = ec.Control.Height Exit Select Case DockStyle.Right rc.Offset(rc.Width - ec.Control.Width, 0) rc.Width = ec.Control.Width Exit Select Case DockStyle.None rc.Size = ec.Control.Size Exit Select End Select ec.Control.Bounds = rc Next Exit Select End Select MyBase.WndProc(m) End Sub End Class End Namespace
Вот что появляется в форме, когда элемент управления перетаскивается в форму:
Imports System Imports System.Drawing Imports System.Collections Imports System.ComponentModel Imports System.Windows.Forms Imports System.Data Namespace ListViewEmbeddedControls Public Class Form1 Inherits System.Windows.Forms.Form Private components As System.ComponentModel.IContainer Public Sub New() InitializeComponent() End Sub Protected Overloads Overrides Sub Dispose(disposing As Boolean) If disposing Then If components Is Nothing Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub Private Sub InitializeComponent() Dim ListViewGroup1 As System.Windows.Forms.ListViewGroup = New System.Windows.Forms.ListViewGroup("personal", System.Windows.Forms.HorizontalAlignment.Left) Dim ListViewItem1 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item1") Dim ListViewItem2 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item2") Dim ListViewItem3 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item3") Dim ListViewItem4 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item4") Dim ListViewItem5 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item5") Dim ListViewItem6 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item6") Dim ListViewItem7 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item7") Dim ListViewItem8 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item8") Dim ListViewItem9 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item1") Dim ListViewItem10 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item2") Dim ListViewItem11 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item3") Dim ListViewItem12 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item4") Dim ListViewItem13 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item5") Dim ListViewItem14 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item6") Dim ListViewItem15 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item7") Dim ListViewItem16 As System.Windows.Forms.ListViewItem = New System.Windows.Forms.ListViewItem("Item8") Me.listview1 = New listviewcreatedcontrols.ListViewEmbeddedControls.ListViewEx() Me.columnHeader1 = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader) Me.columnHeader2 = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader) Me.SuspendLayout() ' 'listview1 ' Me.listview1.AllowColumnReorder = True Me.listview1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _ Or System.Windows.Forms.AnchorStyles.Left) _ Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) Me.listview1.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.columnHeader1, Me.columnHeader2}) Me.listview1.FullRowSelect = True Me.listview1.GridLines = True ListViewGroup1.Header = "personal" ListViewGroup1.Name = "Personal" Me.listview1.Groups.AddRange(New System.Windows.Forms.ListViewGroup() {ListViewGroup1}) Me.listview1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None Me.listview1.HideSelection = False Me.listview1.HoverSelection = False Me.listview1.Items.AddRange(New System.Windows.Forms.ListViewItem() {ListViewItem1, ListViewItem2, ListViewItem3, ListViewItem4, ListViewItem5, ListViewItem6, ListViewItem7, ListViewItem8, ListViewItem9, ListViewItem10, ListViewItem11, ListViewItem12, ListViewItem13, ListViewItem14, ListViewItem15, ListViewItem16}) Me.listview1.LabelWrap = False Me.listview1.Location = New System.Drawing.Point(16, 32) Me.listview1.MultiSelect = False Me.listview1.Name = "listview1" Me.listview1.OwnerDraw = True Me.listview1.Size = New System.Drawing.Size(368, 240) Me.listview1.TabIndex = 0 Me.listview1.UseCompatibleStateImageBehavior = False Me.listview1.View = System.Windows.Forms.View.Details ' 'columnHeader1 ' Me.columnHeader1.Text = "ColumnHeader1" Me.columnHeader1.Width = 119 ' 'columnHeader2 ' Me.columnHeader2.Text = "ColumnHeader2" Me.columnHeader2.Width = 124 ' 'Form1 ' Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(400, 302) Me.Controls.Add(Me.listview1) Me.Name = "Form1" Me.Text = "Sample for Controls embedded in a ListView" Me.ResumeLayout(False) End Sub <STAThread> Shared Sub Main() Application.EnableVisualStyles() Application.Run(New Form1()) End Sub Private WithEvents columnHeader1 As ColumnHeader Private WithEvents columnHeader2 As ColumnHeader Friend WithEvents ListViewEx As ListViewEx Private listview1 As ListViewEx Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load Dim cb As New ComboBox() cb.Text = "tryme" listview1.AddEmbeddedControl(cb, 0, 4) For I = 0 To listview1.Items.Count - 1 listview1.Items.Item(I).SubItems.Add("") Next End Sub End Class End Namespace
Как уже говорилось выше, я подумал, что вполне возможно, что что-то в классе мешает производству предметов. Вот почему изначально я просто разместил этот класс.
Что я уже пробовал:
Я попытался реализовать фазу загрузки с помощью элементов. Однако, если есть способ загрузить элементы в фактический класс, это может помочь.
Richard MacCutchan
Вы объявили свой ListView нарисованным владельцем; где находится обработчик событий OwnerDraw? Откровенно говоря, это выглядит слишком сложным, чтобы просто создать listview с 16 фиксированными строками.
Member 11856456
Ричард, я не возражаю. Однако цель состоит в том, чтобы иметь возможность вставлять и удалять элементы управления, нажав на элемент listview. Однако, поскольку listview не появляется, я понятия не имею, будет ли часть кода встраивания работать правильно, и даже если это произойдет, мне все равно нужен способ удалить встроенный элемент управления, как только я закончу.
Richard MacCutchan
Тогда вы должны забыть о встраивании и получить базовое представление списка, работающее. То, что вы можете сделать с помощью всего лишь нескольких щелчков мыши в конструкторе.
Member 11856456
Может быть, я смогу использовать обычный listview. Есть ли способ встраивать и удалять встроенные элементы управления без создания пользовательского listview?
Richard MacCutchan
К сожалению, это не то, что я когда-либо пытался сделать.
Member 11856456
Я обнаружил, что изменение кода моего класса на 64x исправит эту проблему. Однако по какой-то странной причине код не будет работать в среде 64x.