C# 由于索引不正确,拖放面板控件重叠

C# 由于索引不正确,拖放面板控件重叠,c#,winforms,C#,Winforms,我正在试验一个表单,它包含一些垂直堆叠的面板,我正在尝试实现一些拖放操作,以便它们可以重新排序。除了一个我不知道的bug之外,它工作得很好。 前提是它是一个文件列表,必须保持垂直堆叠,但可以根据用户认为合适的情况重新排序,以形成我稍后生成的文档的页面列表 试试下面的代码,你会得到一个有6个堆叠面板的表单。单击并向上或向下拖动其中任何一个,它们将重新排序 问题在于,如果你非常快地上下拖动一个,它们就会开始相互重叠。 我把快捷键CTRL+B放在那里,在任何给定的时间列出当前面板的顶部位置,你会看到在

我正在试验一个表单,它包含一些垂直堆叠的面板,我正在尝试实现一些拖放操作,以便它们可以重新排序。除了一个我不知道的bug之外,它工作得很好。
前提是它是一个文件列表,必须保持垂直堆叠,但可以根据用户认为合适的情况重新排序,以形成我稍后生成的文档的页面列表

试试下面的代码,你会得到一个有6个堆叠面板的表单。单击并向上或向下拖动其中任何一个,它们将重新排序

问题在于,如果你非常快地上下拖动一个,它们就会开始相互重叠。
我把快捷键CTRL+B放在那里,在任何给定的时间列出当前面板的顶部位置,你会看到在不应该的时候,你会得到重复的数字

问题在于MouseMove事件。我敢肯定,这有点像是一个竞争条件,字典跟不上,或者索引计算速度不够快,但我挠头了。我已尝试锁定它们,但没有效果。
我相信有更好的方法来实现这一点,所以我愿意接受建议,但考虑到这将永远不会有超过30个面板,这符合我的需要

很抱歉弄脏了,我打算稍后再收拾

public Form1()
{
    InitializeComponent();
    this.SuspendLayout();
    this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    this.ClientSize = new System.Drawing.Size(284, 601);
    this.DoubleBuffered = true;
    this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
    this.MaximizeBox = false;
    this.MaximumSize = new System.Drawing.Size(300, 640);
    this.MinimumSize = new System.Drawing.Size(300, 640);
    this.Name = "Form1";
    this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
    this.Text = "Form1";
    this.Load += new System.EventHandler(this.Form1_Load);
    this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
    this.ResumeLayout(false);
}

Dictionary<int, Panel> panelPositions = new Dictionary<int, Panel>();
static Random rnd = new Random();
int y;
int start;
static int index, previndex, currentindex, newindex, maxindex;
bool isDragging;
Panel currentPanel;
static readonly object Lock = new Object();

private void Form1_Load(object sender, EventArgs e)
{
    Width = 300;
    Height = 640;
    int count = 5;
    int currentTop = 0;
    for (int i = 0; i <= count; i++)
    {
        Panel panel = new Panel();
        panel.Width = 300;
        panel.Height = 100;
        panel.Top = currentTop;
        panel.BackColor = RandomColor();
        panel.Margin = Padding.Empty;
        panel.Padding = Padding.Empty;
        panel.BorderStyle = BorderStyle.None;

        Label label = new Label();
        label.Font = new Font("Segoe UI", 24.0f);
        label.Text = (i + 1).ToString();
        label.Top = 20;
        label.Left = 20;
        label.AutoSize = true;

        panel.Controls.Add(label);
        panel.MouseDown += new MouseEventHandler(MouseisDown);
        panel.MouseMove += new MouseEventHandler(MouseMoves);
        panel.MouseUp += new MouseEventHandler(MouseisUp);

        lock (Lock)
        {
            panelPositions.Add(i, panel);
        }

        Controls.Add(panel);

        currentTop += 100;
    }

    lock (Lock)
    {
        maxindex = panelPositions.Count - 1;
    }
}

private void MouseisUp(object sender, MouseEventArgs e)
{
    if (isDragging)
    {
        if (newindex < maxindex)
        {
            currentPanel.Top = newindex * 100;
        }
        else
        {
            currentPanel.Top = maxindex * 100;
        }
    }

    isDragging = false;
}

// I'M SURE THE PROBLEM IS IN HERE SOMEWHERE.
private void MouseMoves(object sender, MouseEventArgs e)
{
    // CHECK THE MOUSE IS STILL DOWN
    if (isDragging)
    {
        // DRAG PANEL VERTICALLY WITH MOUSE
        currentPanel.Location = new Point(currentPanel.Left, e.Y + currentPanel.Top - y);

        // WORK OUT NEW INDEX POSITION
        newindex = 0;
        if ((currentPanel.Top + e.Y) > 0)
        {
            newindex = ((currentPanel.Top + e.Y) / 100);
        }

        // NEW POSITION?
        if (currentindex != newindex)
        {
            // TRACK CHANGES
            previndex = currentindex;
            currentindex = newindex;

            /* PRETTY SURE IT'S THIS BIT THAT'S WRONG */
            // CHECK WE'RE NOT OUT OF BOUNDS
            if (currentindex <= maxindex)
            {
                lock (Lock)
                {
                    // RE-ARRANGE PANEL INDEX
                    panelPositions[previndex] = panelPositions[currentindex];
                    panelPositions[currentindex] = currentPanel;
                    panelPositions[previndex].Top = previndex * 100;
                }
            }
        }
    }
}

private void MouseisDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        currentPanel = sender as Panel;
        isDragging = true;
        currentPanel.BringToFront();
        y = e.Y;
        start = currentPanel.Top;

        int i = 0;
        if (currentPanel.Top > 0)
        {
            i = currentPanel.Top;
            i = (i / 100);
        }
        index = i;

        previndex = i;
        currentindex = i;
    }
    else
    {
        isDragging = false;
    }
}

private Color RandomColor()
{
    Color randColor;

    randColor = Color.FromArgb(RandomRGB(), RandomRGB(), RandomRGB());

    return randColor;
}
private int RandomRGB()
{
    return rnd.Next(1, 256);
}

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.KeyCode == Keys.B)
    {
        string message = string.Empty;
        int count = panelPositions.Count;
        for (int i = 0; i < count; i++)
        {
            message += @"Panel " + i.ToString() + @": " + panelPositions[i].Top.ToString() + Environment.NewLine;
        }
        MessageBox.Show(message);
    }
}
public Form1()
{
初始化组件();
这个.SuspendLayout();
此.AutoScaleDimensions=新系统.Drawing.SizeF(6F,13F);
this.AutoScaleMode=System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize=新系统.Drawing.Size(284601);
this.DoubleBuffered=true;
this.FormBorderStyle=System.Windows.Forms.FormBorderStyle.FixedSingle;
this.ebox=false;
this.MaximumSize=新系统图纸尺寸(300640);
this.MinimumSize=新系统图纸尺寸(300640);
this.Name=“Form1”;
this.StartPosition=System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text=“Form1”;
this.Load+=new System.EventHandler(this.Form1\u Load);
this.KeyDown+=new System.Windows.Forms.KeyEventHandler(this.Form1\u KeyDown);
此选项为.resume布局(false);
}
字典面板位置=新字典();
静态随机rnd=新随机();
int-y;
int启动;
静态int索引、previndex、currentindex、newindex、maxindex;
布尔伊斯特拉格;
面板电流面板;
静态只读对象锁=新对象();
私有void Form1\u加载(对象发送方、事件参数e)
{
宽度=300;
高度=640;
整数计数=5;
int currentTop=0;
对于(inti=0;i变化

//新职位?

如果(currentindex!=newindex&&newindex再次尝试。如果currentindex不在prevIndex的绑定内,请在离开前重置它。我想是这样的。如果您将其作为答案发布,我将接受。很抱歉现在外出工作,如果您愿意接受其他解决方案,没有时间写完整的解释性答案……不需要大量的ans呃,我明白你的意思,用一行代码就解决了;-)谢谢你的帮助。因为你有117k代表,我会接受另一个答案。
    // NEW POSITION?
    if (currentindex != newindex)
    // NEW POSITION?
    if (currentindex != newindex && newindex <= maxindex)