防止在 C# DataGridView 中单击 DataRow 的 Button 时引发 SelectionChanged 事件
Prevent raising SelectionChanged event on a DataRow's Button click within a C# DataGridView
我有一个包含按钮列的 DataGridView。
DataGridView 中的每条记录都有一个单独的按钮。包含行特定数据的 QueueMusic 对象应在单击行的按钮时排队。
我目前通过使用该集合的 .Enqueue()
方法将自定义 class (QueueMusic) 放置到 Queue
集合上来实现此目的。
我有两个事件处理程序方法。
DataGridViewAllMusic_SelectionChanged
方法,开始播放与当前按钮行关联的音乐。
DataGridViewAllMusic_CellClick
方法,它处理与当前 Button 的行关联的播放列表(在 QueueMusic class 中定义)的排队。
问题
- 播放音乐后,每次后续单击 Row 的按钮都会中断当前正在播放的音乐,并使用由最新的 Row 的 QueueMusic 对象定义的音乐。
我有一个 class QueueMusic。
internal class QueueMusic
{
public string Url { get; set; }
public int RowIndex { get; set; }
public static Queue<QueueMusic> queulist = new Queue<QueueMusic>();
}
和一个 DataGridView CellClickEvent
private void DataGridViewAllMusic_CellClick(object sender, DataGridViewCellEventArgs
e)
{
var senderGrid = (DataGridView)sender;
if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >=
0)
{
QueueMusic qm = new QueueMusic();
qm.RowIndex = e.RowIndex;
qm.Url = DataGridViewAllMusic.Rows[e.RowIndex].Cells[2].Value.ToString();
QueueMusic.queulist.Enqueue(qm);
}
}
private void DataGridViewAllMusic_SelectionChanged(object sender, EventArgs e)
{
play();
}
期望的行为
当音乐已经在播放时,如何防止 DataGridViewAllMusic_SelectionChanged
处理 Row 的按钮单击事件?
期望的行为是在不中断当前播放列表的情况下在后台对下一个播放列表进行排队。
您在此处编写 post 时省略了代码的几个关键部分。
您需要包含 play()
方法的逻辑。了解那里发生的事情将极大地帮助我们帮助您。
例如,哪些数据来自您注入每个 QueueMusic 实例的 URL?
您肯定需要定义一个 Form-level 属性 来保存您拥有的任何 Queue 或 Music class 的单个实例。一旦在表单加载时实例化,该对象只应在您单击行的按钮时添加到。您需要在播放列表完成时处理出队;也许这是由您未显示的其他代码处理的。
您在 QueueMusic 中定义的静态队列不是一个好的设计。
每次单击时音乐播放列表都会重新开始,因为每次单击都会覆盖 QueueMusic 对象。
我建议如下:
internal class MusicQueue
{
public MusicQueue()
{
PlaylistQueue = new Queue<Playlist>();
// any other setup...
}
public Queue<Playlist> Playlist { get; set; }
}
internal class Playlist
{
public string Url { get; set; }
public int RowIndex { get; set; }
public void Play()
{
// ?
}
public bool IsPlaying { get; set; }
}
在表单的主要 class 代码中,执行以下操作:
...
private MusicQueue queue { get; set; }
private void Form1_Load(object sender, EventArgs e)
{
queue = new MusicQueue();
// any other setup...
}
...
然后在两个处理程序中:
private void DataGridViewAllMusic_CellClick(object sender, DataGridViewCellEventArgs e)
{
...
// get data from the DataGridView's Row
// put the new playlist on the queue
// you may want to check if the current Row's playlist is already on the queue
queue.Playlist.Add(new Playlist() { (construct the new playlist here) };
}
private void DataGridViewAllMusic_SelectionChanged(object sender, EventArgs e)
{
// depends on what `play()` is doing, but I'd probably
// suggest checking if any playlist is playing.
// if not, start the first playlist
if (queue.Playlist.Any(p => p.IsPlaying)
{
queue.Playlist.FirstOrDefault().Play();
}
}
我有一个包含按钮列的 DataGridView。
DataGridView 中的每条记录都有一个单独的按钮。包含行特定数据的 QueueMusic 对象应在单击行的按钮时排队。
我目前通过使用该集合的 .Enqueue()
方法将自定义 class (QueueMusic) 放置到 Queue
集合上来实现此目的。
我有两个事件处理程序方法。
DataGridViewAllMusic_SelectionChanged
方法,开始播放与当前按钮行关联的音乐。DataGridViewAllMusic_CellClick
方法,它处理与当前 Button 的行关联的播放列表(在 QueueMusic class 中定义)的排队。
问题
- 播放音乐后,每次后续单击 Row 的按钮都会中断当前正在播放的音乐,并使用由最新的 Row 的 QueueMusic 对象定义的音乐。
我有一个 class QueueMusic。
internal class QueueMusic
{
public string Url { get; set; }
public int RowIndex { get; set; }
public static Queue<QueueMusic> queulist = new Queue<QueueMusic>();
}
和一个 DataGridView CellClickEvent
private void DataGridViewAllMusic_CellClick(object sender, DataGridViewCellEventArgs
e)
{
var senderGrid = (DataGridView)sender;
if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >=
0)
{
QueueMusic qm = new QueueMusic();
qm.RowIndex = e.RowIndex;
qm.Url = DataGridViewAllMusic.Rows[e.RowIndex].Cells[2].Value.ToString();
QueueMusic.queulist.Enqueue(qm);
}
}
private void DataGridViewAllMusic_SelectionChanged(object sender, EventArgs e)
{
play();
}
期望的行为
当音乐已经在播放时,如何防止 DataGridViewAllMusic_SelectionChanged
处理 Row 的按钮单击事件?
期望的行为是在不中断当前播放列表的情况下在后台对下一个播放列表进行排队。
您在此处编写 post 时省略了代码的几个关键部分。
您需要包含 play()
方法的逻辑。了解那里发生的事情将极大地帮助我们帮助您。
例如,哪些数据来自您注入每个 QueueMusic 实例的 URL?
您肯定需要定义一个 Form-level 属性 来保存您拥有的任何 Queue 或 Music class 的单个实例。一旦在表单加载时实例化,该对象只应在您单击行的按钮时添加到。您需要在播放列表完成时处理出队;也许这是由您未显示的其他代码处理的。
您在 QueueMusic 中定义的静态队列不是一个好的设计。
每次单击时音乐播放列表都会重新开始,因为每次单击都会覆盖 QueueMusic 对象。
我建议如下:
internal class MusicQueue
{
public MusicQueue()
{
PlaylistQueue = new Queue<Playlist>();
// any other setup...
}
public Queue<Playlist> Playlist { get; set; }
}
internal class Playlist
{
public string Url { get; set; }
public int RowIndex { get; set; }
public void Play()
{
// ?
}
public bool IsPlaying { get; set; }
}
在表单的主要 class 代码中,执行以下操作:
...
private MusicQueue queue { get; set; }
private void Form1_Load(object sender, EventArgs e)
{
queue = new MusicQueue();
// any other setup...
}
...
然后在两个处理程序中:
private void DataGridViewAllMusic_CellClick(object sender, DataGridViewCellEventArgs e)
{
...
// get data from the DataGridView's Row
// put the new playlist on the queue
// you may want to check if the current Row's playlist is already on the queue
queue.Playlist.Add(new Playlist() { (construct the new playlist here) };
}
private void DataGridViewAllMusic_SelectionChanged(object sender, EventArgs e)
{
// depends on what `play()` is doing, but I'd probably
// suggest checking if any playlist is playing.
// if not, start the first playlist
if (queue.Playlist.Any(p => p.IsPlaying)
{
queue.Playlist.FirstOrDefault().Play();
}
}