我想用ListBox播放列表構建一個簡單的音樂播放器。將音頻文件添加到播放列表時,首先用文件名填充列表框,然後(在單獨的線程上)提取ID3數據並用正確的藝術家 - 標題信息覆蓋文件名(很像Winamp)。防止列表框滾動到頂部時更新
但是當ListBox被更新時,它是不可滾動的,因爲它總是跳到每個項目覆蓋的頂部。
任何方式來防止這種情況?
編輯:
代碼:
public Form1()
{
//Some initialization code omitted here
BindingList<TAG_INFO> trackList = new BindingList<TAG_INFO>();
// 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 > 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 < 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);
}
EDIT2:
簡單多了測試用例:
嘗試向下滾動而不選擇一個項目。不斷變化的ListBox將再次滾動到頂部。
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 && (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 < 45; i++)
listBox1.Items.Add(i);
}
int tickCounter = -1;
private void timer1_Tick(object sender, EventArgs e)
{
if (++tickCounter > 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());
}
}
}
您可以發表一些代碼。它的更新方式可能與問題有關。 – 2010-05-22 18:15:52
當然。已添加代碼。 – WDZ 2010-05-22 19:35:20
添加了更簡單的代碼來演示相同的問題。 – WDZ 2010-05-22 20:25:33