拖放FlowLayoutPanel中的多个项目

时间:2012-09-21 15:38:01

标签: c# winforms flowlayoutpanel

我有一个使用FlowLayoutPanel的WinForm应用程序,它显示有多个页面的.TIFF文件。 FlowLayoutPanel显示ThumbNails视图中的所有页面。

我已经实现了Drag Drop Logic,它适用于单个项目。现在,我现在想要更改它以允许用户选择多个缩略图(使用CTRL或Shift键)并拖放到不同的位置。

//** Logic after each thumbnail is generated:
PictureBox thumb = new myProject.utility.PictureBox(pageNum);

thumb.Image = doc.getThumb(pageNum);  //since we pre loaded, we won't stall the gui thread.
thumb.Click += new System.EventHandler(
    (thumbSend, thumbEvent) =>
    {
        highLightThumb(thumb.getPage());
    }
);
thumb.DoubleClick += new System.EventHandler(
    (thumbSend, thumbEvent) =>
    {
        selectedDoc = thumb.getPage();
        me.Visible = false;
    }
);
thumbFlow.Controls.Add(thumb);
if (selectedDoc == pageNum)
    highLightThumb(pageNum);



//** Highlight Methods
private void highLightThumb(int page)
{
   //clear highlight
    foreach (Control c in thumbFlow.Controls)
    {
        if (c is PictureBox)
        {
            ((PictureBox)c).highlight = false;
         }
    }

    //apply highlight
    foreach (Control c in thumbFlow.Controls)
    {
        if (c is PictureBox)
        {
            PictureBox thumbFrame = (PictureBox)c;
            if (page == thumbFrame.getPage())
                thumbFrame.highlight = true;
        }
    }

}

以下是现有的拖放逻辑。

//**********************//
//** Drag/Drop Events **//
//**********************//
private void thumbFlow_DragDrop(object sender, DragEventArgs e)
{
    PictureBox data = (PictureBox)e.Data.GetData(typeof(PictureBox));
    FlowLayoutPanel _destination = (FlowLayoutPanel)sender;

    Point p = _destination.PointToClient(new Point(e.X, e.Y));
    var item = _destination.GetChildAtPoint(p);
    if (item == null)
    {
        p.Y = p.Y - 10;
        item = _destination.GetChildAtPoint(p);
    }
    int index = _destination.Controls.GetChildIndex(item, false);
    if (index < 0)
        return;

    _destination.Controls.SetChildIndex(data, index);
    _destination.Invalidate();

}

private void thumbFlow_DragEnter(object sender, DragEventArgs e)
{
    //apply/clear highlight
    foreach (Control c in thumbFlow.Controls)
    {
        if (c is PictureBox)
        {
            PictureBox thumbFrame = (PictureBox)c;
            if (thumbFrame == ActiveControl)
            {
                thumbFrame.highlight = true;
            }
            else
            {
                ((PictureBox)c).highlight = false;
            }
        }
    }
    e.Effect = DragDropEffects.Move;
    if (dragDropOccurred == false)
    {
        dragDropOccurred = true;
    }
}

//** Scroll when user drags above or below the window object  **//
private void thumbFlow_DragLeave(object sender, EventArgs e)
{
    int BegY_ThumbFlow = this.thumbFlow.FindForm().PointToClient(this.thumbFlow.Parent.PointToScreen(this.thumbFlow.Location)).Y;
    int thumbFlowBound_Y = this.thumbFlow.Height + BegY_ThumbFlow;
    int mouseY = this.thumbFlow.FindForm().PointToClient(MousePosition).Y;

    while (mouseY >= thumbFlowBound_Y)
    {
        thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value + DRAG_DROP_SCROLL_AMT;
        mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
        thumbFlow.Refresh();
    }

    while (mouseY <= BegY_ThumbFlow)
    {
        thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value - DRAG_DROP_SCROLL_AMT;
        mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
        thumbFlow.Refresh();
    }

}

我正在查看的选项是更改highLightThumb方法以检查是否选中了CTRL或Shift键而不禁用高亮显示

 if (Control.ModifierKeys != Keys.Control)
 //**
 if (Control.ModifierKeys != Keys.Shift)

然后更改DragDrop DragEnter Routine。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

这是我最终做的事情..

生成缩略图后

PictureBox thumb = new util.PictureBox(pageNum);
thumb.Image = doc.getThumb(pageNum);  //since we pre loaded, we won't stall the gui thread.
thumb.SizeMode = PictureBoxSizeMode.CenterImage;
thumb.BorderStyle = BorderStyle.FixedSingle;
thumb.Click += new System.EventHandler(
    (thumbSend, thumbEvent) =>
    {
        selectThumb(thumb);
    }
);
thumb.DoubleClick += new System.EventHandler(
    (thumbSend, thumbEvent) =>
    {
        selectedDoc = thumb.getPage();
        me.Visible = false;
    }
);
thumbFlow.Controls.Add(thumb);
if (selectedDoc == pageNum)
    selectThumb(thumb);

现在是缩略图选择代码。
在Picturebox逻辑中,我现在有一个名为pageIndex的变量。它是用页码初始化的。这样做的目的是因为正如您稍后将看到的那样,当我旋转我的对象时,如果我更改了childindex值,它似乎立即发生,如果我拖动项目2,3,4它将跳过项目3并且仅移动第2项和第2项所以稍后当我重新排列拇指时,我首先按pageIndex排序。

//*************************************//
//** Thumbnail Selection Processing  **//
//*************************************//
/// <summary>
/// Main Thumbnail selection area.  
///    If the Shift key is held down, look for a search between.  
///    If Ctrl key, do not clear selections as can select multiple.
/// </summary>
private void selectThumb(PictureBox _thumb)
{
    if (Control.ModifierKeys == Keys.Shift)
        if (SelectMultipleThumbs(_thumb.getPageIndex()))  //** if another thumb is selected, select all in between, then exit  **//
            return;

    if (Control.ModifierKeys != Keys.Control)
    {
        ClearAllSelections();
    }
    else
    {
        if (_thumb.IsSelected == true)
        {
            _thumb.IsSelected = false;
            return;
        }
    }

    _thumb.IsSelected = true;
}

/// <summary>
/// Check if there are other selected items.  If there is, select all between the start and end.
/// </summary>
private bool SelectMultipleThumbs(int _pageindex)
{
    //** Check if there are other objects that have been selected **/
    int? otherSelPageIndex = GetPageIndexOfThumbSelected(_pageindex);
    if (otherSelPageIndex != null)
    {
        ApplySelectionBetweenStartEndPageIndex(_pageindex, Convert.ToInt32(otherSelPageIndex));
        return true;
    }
    return false;
}

/// <summary>
/// Apply Selection if between start and end Pages
/// </summary>
private void ApplySelectionBetweenStartEndPageIndex(int _val1, int _val2)
{
    int startThumb = _val1;
    int endThumb = _val2;
    if (_val1 > _val2)
    {
        startThumb = _val2;
        endThumb = _val1;
    }

    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().OrderBy(si => si.pageIndex))
    {
        if (isBetween(thumbFrame.getPageIndex(), startThumb, endThumb))
            thumbFrame.IsSelected = true;
        else
            thumbFrame.IsSelected = false;
    }
}

/// <summary>
/// Clear All Highlight
/// </summary>
private void ClearAllSelections()
{
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>())
    {
        thumbFrame.IsSelected = false;
    }
}

/// <summary>
/// Check for any selected items prior
/// </summary>
private int? GetPageIndexOfThumbSelected(int _pageindex)
{
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>())
    {
        if (thumbFrame.IsSelected &&
            _pageindex != thumbFrame.getPageIndex())
        {
            return thumbFrame.getPageIndex();
        }
    }
    return null;
}

现在处理拖拽。

private void thumbFlow_DragDrop(object sender, DragEventArgs e)
{
    FlowLayoutPanel _destination = (FlowLayoutPanel)sender;

    Point p = _destination.PointToClient(new Point(e.X, e.Y));
    var item = _destination.GetChildAtPoint(p);
    if (item == null)
    {
        p.Y = p.Y - 10;
        item = _destination.GetChildAtPoint(p);
    }
    int dropIndexValue = _destination.Controls.GetChildIndex(item, false);
    if (dropIndexValue < 0)
        return;

    //**************************************************//
    //**  Process multiple Select Drag / Drop   
    //**    If Drag From > Drag To, move after.
    //**    If Drag From < Drag To, move before.
    //**************************************************//

    //** First .. Find all items that are selected **//
    Boolean WasDragUp = false;
    int? firstDragIndexValue = null;
    int newIndexVal = dropIndexValue;
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().Where(selVal => selVal.IsSelected))
    {
        if (firstDragIndexValue == null)
        {
            firstDragIndexValue = _destination.Controls.GetChildIndex(thumbFrame, false);
            if (firstDragIndexValue > dropIndexValue)
                WasDragUp = true;
        }
        thumbFrame.pageIndex = newIndexVal;
        newIndexVal++;
    }

    //** Second .. Find all items that are NOT selected **//
    if (WasDragUp)
    {
        newIndexVal = 0;
        foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().Where(selVal => !selVal.IsSelected))
        {
            if (_destination.Controls.GetChildIndex(thumbFrame, false) == dropIndexValue)
                if (newIndexVal <= dropIndexValue)
                    newIndexVal = dropIndexValue + getThumbSelectedCnt();
            thumbFrame.pageIndex = newIndexVal;
            newIndexVal++;
        }
    }
    else
    {
        newIndexVal = 0;
        foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().Where(selVal => !selVal.IsSelected))
        {
            thumbFrame.pageIndex = newIndexVal;
            if (_destination.Controls.GetChildIndex(thumbFrame, false) == dropIndexValue)
            {
                newIndexVal = dropIndexValue + getThumbSelectedCnt();
            }
            newIndexVal++;
        }
    }

    //** Third .. Set the Child Index value  **//
    newIndexVal = 0;
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().OrderBy(si => si.pageIndex))
    {
        thumbFrame.pageIndex = newIndexVal;
        _destination.Controls.SetChildIndex(thumbFrame, thumbFrame.pageIndex);
        thumbFrame.IsSelected = false;
        newIndexVal++;
    }

    //** Finally, rebuild the screen  **//
    _destination.Invalidate();

}

private void thumbFlow_DragEnter(object sender, DragEventArgs e)
{
    //apply/clear highlight
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>())
    {
        if (thumbFrame == ActiveControl)
        {
            thumbFrame.IsSelected = true;
        }
    }

    e.Effect = DragDropEffects.Move;
    if (dragDropOccurred == false)
    {
        dragDropOccurred = true;
    }
}

/// <summary>
/// Scroll when user drags above or below the window object.
/// </summary>
private void thumbFlow_DragLeave(object sender, EventArgs e)
{
    int BegY_ThumbFlow = this.thumbFlow.FindForm().PointToClient(this.thumbFlow.Parent.PointToScreen(this.thumbFlow.Location)).Y;
    int thumbFlowBound_Y = this.thumbFlow.Height + BegY_ThumbFlow;
    int mouseY = this.thumbFlow.FindForm().PointToClient(MousePosition).Y;

    while (mouseY >= thumbFlowBound_Y)
    {
        thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value + DRAG_DROP_SCROLL_AMT;
        mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
        thumbFlow.Refresh();
    }

    while (mouseY <= BegY_ThumbFlow)
    {
        thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value - DRAG_DROP_SCROLL_AMT;
        mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
        thumbFlow.Refresh();
    }

}

更新文件

我会把我的代码放在这里但是对于每个人他们计划做的事情它确实更具体。我基本上重建了文件并保存了它。