Domanda

I got the problem that I need a CheckedListBox where I can check the box by clicking at an item and also be able to reorder the Items by drag&drop.

I implemented this with the following code:

private void chLB_BenötigteProzesse_MouseDown(object sender, MouseEventArgs e)
{
    if (this.chLB_BenötigteProzesse.SelectedItem == null)
        return;
    indexBefore = this.chLB_BenötigteProzesse.SelectedIndex;
    this.chLB_BenötigteProzesse.DoDragDrop(this.chLB_BenötigteProzesse.SelectedItem, DragDropEffects.Move);
}

private void chLB_BenötigteProzesse_DragOver(object sender, DragEventArgs e)
{
    e.Effect = DragDropEffects.Move;
}

private void chLB_BenötigteProzesse_DragDrop(object sender, DragEventArgs e)
{
    Point point = chLB_BenötigteProzesse.PointToClient(new Point(e.X, e.Y));
    int index = this.chLB_BenötigteProzesse.IndexFromPoint(point);
    if (index < 0) index = this.chLB_BenötigteProzesse.Items.Count - 1;
    if (index == indexBefore)
    {
        this.chLB_BenötigteProzesse.SetItemChecked(index, !this.chLB_BenötigteProzesse.GetItemChecked(index));
        return;
    }
    object data = e.Data.GetData(typeof(string));
    this.chLB_BenötigteProzesse.Items.Remove(data);
    this.chLB_BenötigteProzesse.Items.Insert(index, data);
}

The problem is, with the _MouseDown event the CheckOnClick is not working anymore. So I tried to fix this with the indexBefore = ... in _MouseDown and if (index == indexBefore)... in DragDrop. This is only working if I click at an Item and move it a little bit that it is being dragged at the same place as it was before. A simple click is also not working.

Next try was to use this mechanism at the _MouseUp event:

    private void chLB_BenötigteProzesse_MouseUp(object sender, MouseEventArgs e)
    {
        Point point = chLB_BenötigteProzesse.PointToClient(new Point(e.X, e.Y));
        int index = this.chLB_BenötigteProzesse.IndexFromPoint(point);
        if (index == indexBefore)
            this.chLB_BenötigteProzesse.SetItemChecked(index, !this.chLB_BenötigteProzesse.GetItemChecked(index));
    }

But _MouseUp is never fired.

Can you tell me how to get this working as it should (simply click on an Item should check/uncheck it and drag&drop should be used to change the order)? Does anyone know why the _MouseUp event isn't fired?

Thanks!

EDIT:

With this Code it is working (couldn't use the e.LeftButton because it's winforms not wpf):

    private void chLB_BenötigteProzesse_DragOver(object sender, DragEventArgs e)
    {
        e.Effect = DragDropEffects.Move;
    }

    private void chLB_BenötigteProzesse_DragDrop(object sender, DragEventArgs e)
    {
        Point point = chLB_BenötigteProzesse.PointToClient(new Point(e.X, e.Y));
        int index = this.chLB_BenötigteProzesse.IndexFromPoint(point);
        if (index < 0) index = this.chLB_BenötigteProzesse.Items.Count - 1;
        if (index == indexBefore)
        {
            this.chLB_BenötigteProzesse.SetItemChecked(index, !this.chLB_BenötigteProzesse.GetItemChecked(index));
            return;
        }

        object data = e.Data.GetData(typeof(string));
        bool checkState = chLB_BenötigteProzesse.GetItemChecked(indexBefore);
        this.chLB_BenötigteProzesse.Items.Remove(data);
        this.chLB_BenötigteProzesse.Items.Insert(index, data);
        this.chLB_BenötigteProzesse.SetItemChecked(index, checkState);
    }

    private void chLB_BenötigteProzesse_MouseMove(object sender, MouseEventArgs e)
    {
        if (!dragDropEnabled || this.chLB_BenötigteProzesse.SelectedItem == null || e.Location == mouseLocation)
            return;

        indexBefore = this.chLB_BenötigteProzesse.SelectedIndex;
        dragDropEnabled = false;
        this.chLB_BenötigteProzesse.DoDragDrop(this.chLB_BenötigteProzesse.SelectedItem, DragDropEffects.Move);
    }

    private void chLB_BenötigteProzesse_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            dragDropEnabled = true;
            mouseLocation = e.Location;
        }
    }
È stato utile?

Soluzione

I would rather use OnMouseMove instead of OnMouseDown and then check if the left mouse button is pressed to start your darag and drop operation as it is described on MSDN.

So the solution to your problem should be to replace chLB_BenötigteProzesse_MouseDown with:

private void chLB_BenötigteProzesse_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed || this.chLB_BenötigteProzesse.SelectedItem == null)
        return;
    indexBefore = this.chLB_BenötigteProzesse.SelectedIndex;
    this.chLB_BenötigteProzesse.DoDragDrop(this.chLB_BenötigteProzesse.SelectedItem, DragDropEffects.Move);    
}

Don't forget to detach your mouseDown handler and attach the new mouseMove handler!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top