title: Preventing ListBox scrolling to top when updated
body: <p>I'm trying to build a simple music player with a ListBox playlist. When adding audio files to the playlist, it first fills the ListBox with the filenames and then (on a separate thread) extracts the ID3 data and overwrites the filenames with the correct Artist - Title information (much like Winamp).</p>
  
  <p>But while the ListBox is being updated, it's unscrollable, as it always jumps to the top on every item overwrite.</p>
  
  <p>Any way to prevent this?</p>
  
  <p><strong>EDIT:</strong><br>
  The code:  </p>
  
  <pre><code>public Form1()
  {
      //Some initialization code omitted here
  
      BindingList&lt;TAG_INFO&gt; trackList = new BindingList&lt;TAG_INFO&gt;();
  
      // The Playlist
      this.playlist = new System.Windows.Forms.ListBox();
      this.playlist.Location = new System.Drawing.Point(12, 12);
      this.playlist.Name = "playlist";
      this.playlist.Size = new System.Drawing.Size(229, 316);
      this.playlist.DataSource = trackList;
  }
  
  private void playlist_add_Click(object sender, EventArgs e)
  {
      //Initialize OpenFileDialog
      OpenFileDialog opd = new OpenFileDialog();
      opd.Filter = "Music (*.WAV; *.MP3; *.FLAC)|*.WAV;*.MP3;*.FLAC|All files (*.*)|*.*";
      opd.Title = "Select Music";
      opd.Multiselect = true;
  
      //Open OpenFileDialog
      if (DialogResult.OK == opd.ShowDialog())
      {
  
          //Add opened files to playlist
          for (int i = 0; opd.FileNames.Length &gt; i; ++i)
          {
              if (File.Exists(opd.FileNames[i]))
              {
                  trackList.Add(new TAG_INFO(opd.FileNames[i]));
              }
          }
  
          //Initialize BackgroundWorker
          BackgroundWorker _bw = new BackgroundWorker();
          _bw.WorkerReportsProgress = true;
          _bw.DoWork += new DoWorkEventHandler(thread_trackparser_DoWork);
          _bw.ProgressChanged += new ProgressChangedEventHandler(_bw_ProgressChanged);
  
          //Start ID3 extraction
          _bw.RunWorkerAsync();
      }
  
  }
  
  void thread_trackparser_DoWork(object sender, DoWorkEventArgs e)
  {
      BackgroundWorker _bw = sender as BackgroundWorker;
  
      for (int i = 0; i &lt; trackList.Count; ++i)
      {
          //Pass extracted tag info to _bw_ProgressChanged for thread-safe playlist entry update
          _bw.ReportProgress(0,new object[2] {i, BassTags.BASS_TAG_GetFromFile(trackList[i].filename)});
      }
  }
  
  void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
  {
      object[] unboxed = e.UserState as object[];
  
      trackList[(int)unboxed[0]] = (unboxed[1] as TAG_INFO);
  }
  </code></pre>
  
  <p><strong>EDIT2:</strong><br>
  Much simpler test case:<br>
  Try scrolling down without selecting an item. The changing ListBox will scroll to the top again.</p>
  
  <pre><code>using System;
  using System.Windows.Forms;
  
  namespace WindowsFormsApplication1
  {
      public class Form1 : Form
      {
          private System.ComponentModel.IContainer components = null;
  
          protected override void Dispose(bool disposing)
          {
              if (disposing &amp;&amp; (components != null))
              {
                  components.Dispose();
              }
              base.Dispose(disposing);
          }
  
          private void InitializeComponent()
          {
              this.components = new System.ComponentModel.Container();
              this.listBox1 = new System.Windows.Forms.ListBox();
              this.timer1 = new System.Windows.Forms.Timer(this.components);
              this.SuspendLayout();
  
              // listBox1
              this.listBox1.FormattingEnabled = true;
              this.listBox1.Location = new System.Drawing.Point(0, 0);
              this.listBox1.Name = "listBox1";
              this.listBox1.Size = new System.Drawing.Size(200, 290);
  
              // timer1
              this.timer1.Enabled = true;
              this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
  
              // Form1
              this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
              this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
              this.ClientSize = new System.Drawing.Size(200, 290);
              this.Controls.Add(this.listBox1);
              this.Name = "Form1";
              this.Text = "Form1";
              this.ResumeLayout(false);
          }
  
          private System.Windows.Forms.ListBox listBox1;
          private System.Windows.Forms.Timer timer1;
  
          public Form1()
          {
              InitializeComponent();
  
              for (int i = 0; i &lt; 45; i++)
                  listBox1.Items.Add(i);
          }
  
          int tickCounter = -1;
  
          private void timer1_Tick(object sender, EventArgs e)
          {
              if (++tickCounter &gt; 44) tickCounter = 0;
              listBox1.Items[tickCounter] = ((int)listBox1.Items[tickCounter])+1;
          }
      }
  
      static class Program
      {
          [STAThread]
          static void Main()
          {
              Application.EnableVisualStyles();
              Application.SetCompatibleTextRenderingDefault(false);
              Application.Run(new Form1());
          }
      }
  }
  </code></pre>