How to set a listview FocusedItem programatically

11.2k views Asked by At

How can I set the FocusedItem property programatically?

I've tried this so far with no success:

If lvw.FocusedItem Is Nothing Then
    If lvw.Items.Count > 0 Then
    lvw.Focus()
    lvw.HideSelection = False
    lvw.Items(0).Selected = True
    lvw.Items(0).Focused = True
    lvw.FocusedItem = lvw.Items(0)
    lvw.Select()
    End If
End If

btw the form where the listview is has not called the ShowDialog method yet. Can this be the reason for this not to work?

2

There are 2 answers

5
Josh On

As others have commented, your code should work as written. If all you need is to programmatically access the focused item in your code, you shouldn't be experiencing any difficulties. (If you are, please describe them.)

If you are looking for a visual effect (the row being highlighted), my guess is that your code is in another control's event and the focus is being set back to that control automatically the instant after your code runs. More than likely your code needs to be where it is and trying to move it elsewhere to prevent this issue would be a waste of time.

However, there are other ways to set a row apart visually. When a list view isn't likely to stay focused, my preferred method is to distinguish the selected item with a different fore/back color. (You can use the focused item if you prefer, but I find the selected item more useful. Your call.)

Here is an example which visually highlights the selected row, regardless of focus:

Private Sub lvw_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lvw.SelectedIndexChanged
    If lvw.Items Is Nothing Then Exit Sub
    For Each lvi As ListViewItem In lvw.Items
        If lvi.Selected = True Then
            lvi.ForeColor = Color.DarkGray
            lvi.BackColor = Color.LightCyan
        Else
            lvi.ForeColor = Color.Black
            lvi.BackColor = Color.White
        End If
    Next
End Sub

EDIT:

In response to the added information that this form is being displayed using ShowDialog, yes, that is likely the source of your problem.

ShowDialog creates a new instance of the form. Therefore, if you have set any properties of a form or its controls, and later call ShowDialog to display that form, the form displayed is a new copy of the original form and will not reflect the changes you made programatically.

Imagine you sit down at a computer where a blank Word document is already open. You type something in it and then open a new document. The text you typed in the first document is not copied to the second. I think this is the root of your troubles here.

0
TnTinMn On

You have to understand that each control on the Form and the Form itself is a window and for the window to have focus it must first be created and assigned a handle.

For a basic description of this, I refer you to: All About Handles in Windows Forms The following excerpts are from the referenced article.

What is a Handle?

A handle (HWND) is the return value from CreateWindowEx which the Windows Operating System uses to identify a window. A "window" in win32 is a much broader concept than you may think - each individual button, combobox, listbox etc comprises a window. (For more information see About Window Classes ) NOTE: there are other things known as "Handles" in the Framework - e.g. GDI Handles from a Bitmap or Handles to Device Contexts (HDCs) - this article discusses HWNDs only.

...

When does a Control create its handle? (When does a control call CreateWindowEx?)

A control tries as much as possible to defer creating its handle. This is because setting properties forces chatty interop between the CLR and user32.

Typically the handles for all the controls are created before the Form.Load event is called. Handles can also be created if the "Handle" property is called and the handle has not yet been created, or CreateControl() is called.

So a window's handle is not immediately created when you instantiate a control. However, you can force a control to create its handle by referencing its Handle property.

So if you first get the ListView to create its handle, then when you set those properties that you wanted.

Dim f2 As New Form2
' you do not need this condition, it is here only for demonstration purposes
' so that you can step through the code in the debugger and observe the
' code execution.
If Not f2.ListView1.IsHandleCreated Then
   ' retrieval of the Handle will cause a handle to be created
   ' if it has not yet been created
   ' if you delete the If-Then block, you will need to retain the 
   ' following statement

   Dim h As IntPtr = f2.ListView1.Handle
End If

f2.ListView1.FocusedItem = f2.ListView1.Items(2)
f2.ListView1.Items(2).Selected = True
f2.ListView1.Items(2).Focused = True
f2.ActiveControl = f2.ListView1
f2.ShowDialog()