【问题标题】:WPF drag-drop rearrangeable wrappanel itemsWPF 拖放可重新排列的包装面板项目
【发布时间】:2015-12-28 22:06:02
【问题描述】:

我需要一些可以排列/排序项目的东西,比如包装面板,但允许您通过拖放重新排列项目。我正在尝试尽快对其进行原型制作,所以我现在只是在寻找一些愚蠢的简单或hacky的东西。我一直在寻找所有地方,但我能找到的唯一答案需要相对大量的工作来实施。

如果可能的话,我宁愿不使用现有的库。

编辑

澄清一下:我需要在一个控件中拖放以及自动重新排列机制来安排项目,如包装面板。

自从发布这个问题以来,我发现了两篇似乎很合适但只有结合起来的帖子/文章。

包装:http://www.codeproject.com/Articles/18561/Custom-ListBox-Layout-in-WPF 拖拽整理:WPF C#: Rearrange items in listbox via drag and drop

当我一切正常后,我会在答案中发布我的代码。

【问题讨论】:

标签: c# wpf wpf-controls


【解决方案1】:

花了一些时间,但在 Micky 的建议下我能够弄清楚。我在这里发布一个答案以供将来参考,如果其他人正在寻找这个机制。以下代码 sn-ps 只需将它们粘贴到相应的文件中即可工作。

以下是有效的:

通过自定义/默认样式(我的称为 Default.xaml)使 ListBox 像 WrapPanel 一样排列项目。

<Style TargetType="{x:Type ListBox}">
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <!--'WrapPanel' can be replaced with other controls if you want it to display differently-->
                <WrapPanel/>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <!--Controls in each item-->
                <local:DocPage />
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>


设置 ListBox 控件(即 MainWindow.xaml):
<ListBox x:Name="lbx_Pages" AllowDrop="True" DragEnter="lbx_Pages_DragEnter" PreviewMouseLeftButtonDown="lbx_Pages_PreviewMouseLeftButtonDown" PreviewMouseMove="lbx_Pages_PreviewMouseMove" Drop="lbx_Pages_PagesDrop"/>


在 .cs 文件(即 MainWindow.xaml.cs)中实现控件:
private Point dragStartPoint;
// Bindable list of pages (binding logic omitted-out of scope of this post)
private static ObservableCollection<DocPage> pages = new ObservableCollection<DocPage>();

// Find parent of 'child' of type 'T'
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
    do
    {
        if (child is T)
            return (T)child;
        child = VisualTreeHelper.GetParent(child);
    } while (child != null);
    return null;
}

private void lbx_Pages_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    dragStartPoint = e.GetPosition(null);
}

private void lbx_Pages_PreviewMouseMove(object sender, MouseEventArgs e)
{

    ListBoxItem item = null;
    DataObject dragData;
    ListBox listBox;
    DocPage page;

    // Is LMB down and did the mouse move far enough to register a drag?
    if (e.LeftButton == MouseButtonState.Pressed &&
        (Math.Abs(dragStartPoint.X - e.GetPosition(null).X) > SystemParameters.MinimumHorizontalDragDistance ||
        Math.Abs(dragStartPoint.Y - e.GetPosition(null).Y) > SystemParameters.MinimumVerticalDragDistance))
    {
        // Get the ListBoxItem object from the object being dragged
        item = FindParent<ListBoxItem>((DependencyObject)e.OriginalSource);

        if (null != item)
        {
            listBox = sender as ListBox;
            page = (DocPage)listBox.ItemContainerGenerator.ItemFromContainer(item);
            dragData = new DataObject("pages", page);

            DragDrop.DoDragDrop(item, dragData, DragDropEffects.Move);
        }
    }
}

private void lbx_Pages_PagesDrop(object sender, DragEventArgs e)
{
    if (!e.Data.GetDataPresent("pages"))
        return;

    DocPage draggedItem = e.Data.GetData("pages") as DocPage;
    // Hit-test needed for rearranging items in the same ListBox
    HitTestResult hit = VisualTreeHelper.HitTest((ListBox)sender, e.GetPosition((ListBox)sender));
    DocPage target = (DocPage)FindParent<ListBoxItem>(hit.VisualHit).DataContext;


    int removeIdx = lbx_Pages.Items.IndexOf(draggedItem);
    int targetIdx = lbx_Pages.Items.IndexOf(target);

    if(removeIdx < targetIdx)
    {
        pages.Insert(targetIdx + 1, draggedItem);
        pages.RemoveAt(removeIdx);
    }
    else
    {
        removeIdx++;
        if(pages.Count+1 > removeIdx)
        {
            pages.Insert(targetIdx, draggedItem);
            pages.RemoveAt(removeIdx);
        }
    }
}

private void lbx_Pages_DragEnter(object sender, DragEventArgs e)
{
    if (!e.Data.GetDataPresent("pages") || sender == e.Source)
        e.Effects = DragDropEffects.None;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 2014-01-22
    • 1970-01-01
    • 2012-07-08
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多