title: Why the Items of a Virtual ListView that are not visible don't have index?
body: <p>I'm working with a ListView in Virtual Mode (.NET 4.6).<br>
  I tried to find the index of Items in the virtual ListView: when I enter a letter, the first item with text that start with that letter should be selected.  </p>
  
  <p>Here is the <code>FindItemWithText</code> in <code>listView1_KeyDown</code>:  </p>
  
  <pre><code>if (char.IsLetterOrDigit(e.KeyChar))
  {
      var str = e.KeyChar.ToString();
      if (tempStr != str)
      {
          Index = 0;
          tempStr = str;
      }
  
      var item = listView1.FindItemWithText(str, false, Index, true);
      if (item != null)
      {
          item.Selected = true;
          item.Focused = true;
          item.EnsureVisible();
          Index = item.Index + 1;
      }
  }
  </code></pre>
  
  <p>Here is my SearchForVirtualItem method:  </p>
  
  <pre><code>var item = lvis.OfType&lt;ListViewItem&gt;().FirstOrDefault(
      i =&gt; i.Text.ToLower().StartsWith(e.Text.ToLower()) &amp;&amp; 
           i.Index &gt;= e.StartIndex);
  if (item == null)
  {
  
  }
  else
  {
      e.Index = item.Index;
  }
  </code></pre>
  
  <p>If the result is one of the visible items before I scroll at all the code works and I can select the result item. But if the result is not visible and I didn't scroll anything at all the method return null.  </p>
  
  <p>But if I scroll to the end of the list even once I can get the index of the item that before I couldn't.  </p>
  
  <blockquote>
    <p>Example: If I have 200 items in a virtual list (populated from a list
    of 200 ListViewItem) and only the first 50 are visible, if I press the <code>c</code>
    letter and items that start with <code>c</code> letter are among the first 50, they will
    be selected.<br>
    But if I press <code>x</code> and the items in the virtual ListView are
    at the last <code>50</code>, the method will return <code>null</code>. If I instead scroll the list to
    the end and then I press <code>x</code>, the items
    that start with <code>x</code> will be selected.  </p>
  </blockquote>
  
  <p>Why I have to show the item at least once to have an index and not having <strong>index = -1</strong>?<br>
  Is this the normal behavior of a virtual ListView or is there something wrong?  </p>
  
  <p>Side question, when does a ListView in <em>normal</em> mode become slow? After <code>100,000</code> items, or <code>1,000,000</code> items?  </p>
  
  <p>Edit1:<br>
  Here is my <code>listView1_RetrieveVirtualItem</code> code:  </p>
  
  <pre><code>private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
  {
      if (lvis.Count &gt; 0)
      {
          e.Item = lvis[e.ItemIndex];
      }
  }
  </code></pre>
  
  <p>I don't use a cache.<br>
  I use BackGroundWorker to get the data from a SQLite database; I create ListViewitems and add them to a List (<code>var lvis = new List&lt;ListViewItem&gt;</code>).  </p>
  
  <p>The <code>RunWorkerCompleted</code> method:  </p>
  
  <pre><code>private void Pl_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  {
      var obj = e.Result;
      if (obj != null)
      {
          RemoveSelection();
  
          lvis = (List&lt;ListViewItem&gt;)obj;
          listView1.Items.Clear();
          listView1.VirtualListSize = lvis.Count;
          listView1.Invalidate();
  
          var No_of_items = listView1.Items.Count + " pin(s)";
          count.Text = No_of_items;
          tabLabel.Text = GetButton().Text + " | " + No_of_items;
      }
  }
  </code></pre>
  
  <p><code>lvis</code> is the source where the virtual ListView get its data from.  </p>