Listview Question

M

Martin Horn

Hi all,

I want to implement a listview with editable subitems and I assume the
easiest way is to overlay a textbox over the item to be edited.

With this in mind I have come up with:

Using fullrowselect=true in the listview

Private Sub ListView1_ItemSelectionChanged(ByVal sender As Object, _
ByVal e As System.Windows.Forms.ListViewItemSelectionChangedEventArgs) _
Handles ListView1.ItemSelectionChanged
Dim t As New TextBox
Me.Controls.Add(t)
t.Location = e.Item.Position
t.BringToFront()
End Sub

Unfortunately item.position only enables me to get the position of the first
column. How can I obtain the x position of the subitem that was clicked.

I have searched google, but the only examples I can find are in C++ which I
can't make any sense of.

Thanks,

Martin.
 
M

Martin Horn

I have found this VB6 example, but I can't figure out how to convert it to
..net, can anyone help me.

Thanks

'Declarations:
Private Type lvwItemClick
x As Long
y As Long
Flgs As Long
Itm As Long
SubItm As Long
End Type

Private Declare Function SendMessage _
Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal lMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long

Dim lvwClick As lvwItemClick

Private Sub ListView1_MouseDown(Button As Integer, _
Shift As Integer, x As Single, y As Single)

lvwClick .x = x / Screen.TwipsPerPixelX
lvwClick .y = y / Screen.TwipsPerPixelY

SendMessage ListView1.hwnd, 4153, 0, lvwClick

If Button = vbRightButton And lvwClick .Itm = 2 And lvwClick .SubItm = 1
Then _
PopupMenu mnuTest 'poppup menu mnuTest for click on Item 3, SubItem 1.

End Sub
 
M

Martin

I'm working on the same thing... Not yet complete, but it's getting there.

Private Sub lstRules_MouseUp(ByVal sender As Object, ByVal e _
As System.Windows.Forms.MouseEventArgs) Handles lstRules.MouseUp
Dim ThisItem As System.Windows.Forms.ListViewItem
Dim NewBox As Control

If Not (e.Button = Windows.Forms.MouseButtons.Left) Then Exit Sub

ThisItem = lstRules.HitTest(e.X, e.Y).Item
If ThisItem Is Nothing Then
Exit Sub
End If

NewBox = New System.Windows.Forms.TextBox
NewBox.Size = New System.Drawing.Size(lstRules.Columns(1).Width - 10,
12)
NewBox.Text = KeyItem.ItemText
NewBox.Location = New System.Drawing.Point(ThisItem.Position.X + _
lstRules.Columns(0).Width + 2,
ThisItem.Position.Y + 1)

Me.Controls.Add(NewBox)
Me.NewBox.BringToFront
AddHandler NewBox.LostFocus, AddressOf DestroyBox
NewBox.Focus()
End Sub

Private Sub DestroyBox(ByVal sender As Object, ByVal e As System.EventArgs)
If sender IsNot Nothing Then
Me.Controls.Remove(sender)
sender.Dispose()
End If
End Sub

Work in progress: Moving the textbox when the user scrolls the Listview.
If you're interested I can post that bit tomorrow

Hth,
Martin
 
M

Martin Horn

Hi Martin,

I have come up with something similar myself, but I can't see how to easily
adapt it to work with scrolling of the listview, so I would definitely be
interested to see your solution.

Here is my version anyway, which retrieves the text from the any of the 6
subitems in my listview and fills the textbox with it when the user double
clicks the listview subitem.

Note: My example doesn't dynamically create the textbox and I have omitted
the code to remove the textbox.

Private Sub ListView1_MouseDoubleClick(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles ListView1.MouseDoubleClick
Dim ItemX As ListViewItem
ItemX = ListView1.GetItemAt(e.X, e.Y)
If ItemX Is Nothing Then Exit Sub

Dim col As Integer = GetColumnNumber(e.X)

EditBox.Top = ItemX.Position.Y
EditBox.Left = GetColumnX(e.X) + 2
EditBox.Text = ListView1.SelectedItems(0).SubItems(col).Text
EditBox.Width = ListView1.Columns(col).Width
EditBox.BringToFront()
EditBox.Focus()
End Sub

Private Function GetColumnNumber(ByVal MouseX As Integer) As Integer
If MouseX < GetTotalWidth(0) Then Return -1
If MouseX < GetTotalWidth(1) Then Return 0
If MouseX < GetTotalWidth(2) Then Return 1
If MouseX < GetTotalWidth(3) Then Return 2
If MouseX < GetTotalWidth(4) Then Return 3
If MouseX < GetTotalWidth(5) Then Return 4
If MouseX < GetTotalWidth(6) Then Return 5
End Function

Private Function GetColumnX(ByVal MouseX As Integer) As Integer
If MouseX < GetTotalWidth(0) Then Return 0
If MouseX < GetTotalWidth(1) Then Return GetTotalWidth(0)
If MouseX < GetTotalWidth(2) Then Return GetTotalWidth(1)
If MouseX < GetTotalWidth(3) Then Return GetTotalWidth(2)
If MouseX < GetTotalWidth(4) Then Return GetTotalWidth(3)
If MouseX < GetTotalWidth(5) Then Return GetTotalWidth(4)
If MouseX < GetTotalWidth(6) Then Return GetTotalWidth(5)
End Function

Private Function GetTotalWidth(ByVal Cols As Integer) As Integer
Dim tot As Integer = 0
For n As Integer = 0 To Cols - 1
tot += ListView1.Columns(n).Width
Next
Return tot
End Function
 
M

Martin

I have changed my objective a bit. Since detecting a scroll event in a
Listview requires me to subclass the Listview (MS simply forgot to raise a
scroll event, although it is built in the API) I am going to do it right.
I'm building a subclass of the Listview that allows any kind of control
(checkbox, combobox, datetimepicker, textbox) to be added as subitem.

If you're interested I will publish the code on my site when I'm done.
 
M

Martin Horn

Although my solution works in the context in which I am using it, I am well
aware that it isn't very efficient and would be very interested in seeing
how you approach the problem, as I am a newbie programmer and what you are
suggesting is well beyond my capabilities at the moment.

If you want to email me the link to your site you can send it to
mvhorn@remove_this_bit.ntlworld.com or post it here instead.

Kind regards,

Martin.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top