Click here to Skip to main content
15,894,646 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
As of now I am getting the listview to appear, however, nothing is appearing in the listview. This is strange because I can see the items and columns show in listview pre-run. Once the program runs the listview is blank.

Here is the code I am using:

Here is the listview control that is created:

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




Here is what appears in the form when the control is dragged over to the form:

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


As stated above I thought is was possible that something in the class was interfering with the items being produced. That is why originally I just posted the class.

What I have tried:

I have tried to implement the load phase with the items. However, if there is a way to load the items into the actual class that may help.
Posted
Updated 10-May-18 3:30am
v4
Comments
Richard MacCutchan 10-May-18 10:56am    
You have declared your ListView as owner drawn; where is the OwnerDraw event handler? Quite frankly that looks far too complicated just to create a listview with 16 fixed strings.
Member 11856456 10-May-18 11:44am    
Richard, I dont disagree. However, the goal is to be able to embed and remove controls by clicking on a listview item. However, Since the listview is not appearing I have no idea if the embedding portion of code will run correctly and even if it does I still need a way to remove the embedded control once I am done.
Richard MacCutchan 10-May-18 11:47am    
Then you should forget about the embedding, and get a basic Listview working. Something that you can do with just a few mouse clicks in the designer.
Member 11856456 10-May-18 11:53am    
Maybe I can use a regular listview. Is there a way to embed and remove embedded controls without creating a custom listview?
Richard MacCutchan 10-May-18 12:12pm    
Sorry, it is not something I have ever tried to do.

1 solution

Not sure why you have a main method inside the form. Go to the application settings and check, what is the setting in Startup form.

Also place a few breakpoints to see if your initialization code is actually hit.
 
Share this answer
 
Comments
Member 11856456 9-May-18 20:59pm    
I had to revise the code in the question. Found out it's not adding to form because there is something missing in the class code portion. Hopefully, I can get help in understanding why it is not working.
Wendelius 10-May-18 2:00am    
In the code you have posted, I can't find any commands that would actually add items to the listview
Member 11856456 10-May-18 9:35am    
I posted the additional code that appears once the control is added to the form. I have to apologize because I thought that it was the control code that was interfering with me seeing the items appear during runtime. It is extremely weird because after the program has run the items appear in the control and you can see them when you look at the form before debugging. However, once the debugging process starts the listview is completely blank on the form.
Wendelius 10-May-18 12:43pm    
So do you mean that during the debug you cannot see the changes in the listview? Looking at the code, the layout is suspended while the items are added:

Me.SuspendLayout()
Member 11856456 10-May-18 15:07pm    
I figured our why this is not working, portion of code is based upon an 86x app, the program I am creating is a 64x. I confirmed this by making different builds with the code in a new project. I do not know where I can change the class code to make it usuable in a 64x program.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900