简体   繁体   English

在WPF C#中的wrappanel内部重新排列CustomControl

[英]Rearrange CustomControl inside wrappanel in wpf c#

I am creating a customcontrol dynamically inside a wrappanel. 我在包装面板内部动态创建一个customcontrol。 Now i need the reorder the custom controls which are inside the wrappanel. 现在,我需要对包装面板中的自定义控件进行重新排序。 Is it possible to rearrange the custom controls inside the wrappanel using drag and drop? 是否可以通过拖放在包装面板内部重新排列自定义控件?

Here is my XAML code 这是我的XAML代码

<DockPanel Grid.Column="1" Margin="208,40,1,94" Grid.Row="2"
                   Background="White" AllowDrop="True">
            <ScrollViewer  AllowDrop="True" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden" Width="443">
                <StackPanel Width="443" > 


                    <WrapPanel x:Name="pnl" HorizontalAlignment="Left" 
                        Height="Auto" 
                        VerticalAlignment="Top" Width="480" AllowDrop="True" 
                         />

                     </StackPanel> 
            </ScrollViewer>
        </DockPanel>

I've tried put the wrap panel inside the list, as it was suggested by the given answer(Ilan's answer), and now my panel is not accessible in the code behind. 我已经尝试将自动换行面板放在列表中,如给定答案(Ilan的答案)所建议的那样,现在在后面的代码中无法访问我的面板。 AM i doing anything wrong? 我做错什么了吗?

在此处输入图片说明

在WrapPanel中拖放

Here I have demonstrated Buttons , you can modify it for your needs. 在这里,我演示了Buttons ,您可以根据需要对其进行修改。

Xaml XAML

<WrapPanel x:Name="Pnl" Background="Yellow" Margin="0,0,0,128" Button.DragEnter="Button_DragEnter" Button.MouseRightButtonDown="Button_MouseDown">
    <Button Content="Btn1" AllowDrop="True"/>
    <Button Content="Btn2" AllowDrop="True"/>
    <Button Content="Btn3" AllowDrop="True"/>
</WrapPanel>

Code

Button btn_to_drag;
private void Button_MouseDown(object sender, MouseButtonEventArgs e)
{
    btn_to_drag = (Button)e.Source;
    DragDrop.DoDragDrop(btn_to_drag, btn_to_drag, DragDropEffects.Move); 
}

private void Button_DragEnter(object sender, DragEventArgs e)
{
    Button btn = (Button)e.Source;
    int where_to_drop = Pnl.Children.IndexOf(btn);
    Pnl.Children.Remove(btn_to_drag);
    Pnl.Children.Insert(where_to_drop, btn_to_drag);
}

Another approach using DataObject removing the need for btn_to_drag declaration. 使用DataObject另一种方法消除了对btn_to_drag声明的需要。

private void Button_MouseDown(object sender, MouseButtonEventArgs e)
{
    DataObject data = new DataObject(DataFormats.Serializable, (Button)e.Source );
    DragDrop.DoDragDrop((DependencyObject)e.Source, data, DragDropEffects.Move);
}

private void Button_DragEnter(object sender, DragEventArgs e)
{
    Button btn_to_move = (Button) e.Data.GetData(DataFormats.Serializable);
            
    int where_to_move = Pnl.Children.IndexOf((UIElement)e.Source);
    int what_to_move = Pnl.Children.IndexOf(btn_to_move);

    Pnl.Children.RemoveAt(what_to_move);
    Pnl.Children.Insert(where_to_move, btn_to_move);
}

Try to put your items into the ItemsControl and set the wrappanel to be the ItemsPanel of the control, then just change the order of the controls inside the items control. 尝试将您的项目放入ItemsControl并将包装面板设置为控件的ItemsPanel,然后仅更改items控件中控件的顺序。 Here is a simple example(put your control into the InputCollection). 这是一个简单的示例(将您的控件放入InputCollection中)。

Update #2 - DragAndDrop 更新#2-DragAndDrop

Xaml XAML

Window x:Class="WpfCSItemsControlWithWrappanelSoHelpAttempt.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid x:Name="RootLayout">
    <ListBox x:Name="ListBowWithWrapPanel" Background="Green" Margin="5" 
             ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Width="250"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ListBox>
    <Button HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Click="ButtonBase_OnClick">Flip</Button>
</Grid>

Code-behind(possible example of drag and drop) 后台代码(可能的拖放示例)

public partial class MainWindow : Window
{
    private readonly ObservableCollection<Shape> _observableCollection;
    private int _coordinator = -1;
    private ListBox _dragSource;
    private Shape _dragedData;
    private Shape _targetData;
    private bool _isInDrag;

    public MainWindow()
    {
        InitializeComponent();

        _observableCollection = new ObservableCollection<Shape>
        {
            new Ellipse{Name = "C", Width = 50, Height = 50, Fill = Brushes.Tomato},
            new Ellipse{Name = "A", Width = 50, Height = 75, Fill = Brushes.Yellow},
            new Rectangle{Name = "Z", Width = 50, Height = 75, Fill = Brushes.Aqua},
            new Rectangle{Name = "D", Width = 50, Height = 75, Fill = Brushes.Blue},
            new Rectangle{Name = "B", Width = 50, Height = 75, Fill = Brushes.CadetBlue},   
            new Ellipse{Name = "X", Width = 75, Height = 25, Fill = Brushes.Aqua},
        };

        ListBowWithWrapPanel.ItemsSource = _observableCollection;

        Style itemContainerStyle = new Style(typeof(ListBoxItem));
        itemContainerStyle.Setters.Add(new Setter(AllowDropProperty, true));
        //we have this to handle a possible dragging element
        itemContainerStyle.Setters.Add(new EventSetter(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(ListBowWithWrapPanel_OnPreviewMouseDown)));
        //we have this to start the dragging process
        itemContainerStyle.Setters.Add(new EventSetter(MouseMoveEvent, new MouseEventHandler(MouseMoveHandler)));
        //we have this to stop the where there is no a dragging process
        itemContainerStyle.Setters.Add(new EventSetter(MouseLeftButtonUpEvent, new MouseButtonEventHandler(LeftButtonUp)));
        //we have this to perform the drop(insert the element into a new position)
        itemContainerStyle.Setters.Add(new EventSetter(DropEvent, new DragEventHandler(ListBowWithWrapPanel_OnDrop)));
        //we have this to handle the possible target position
        itemContainerStyle.Setters.Add(new EventSetter(DragOverEvent, new DragEventHandler(OnDragOver)));
        ListBowWithWrapPanel.ItemContainerStyle = itemContainerStyle;
    }

    /// <summary>
    /// sort when button click
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        var list = _observableCollection.ToList();
        _observableCollection.Clear();

        _coordinator *= -1;

        list.Sort((shape, shape1) =>
        {
            var name1 = shape.Name;
            var name2 = shape1.Name;

            return string.Compare(name1, name2, StringComparison.Ordinal) * _coordinator;
        });

        list.ForEach(shape =>
        {
            _observableCollection.Add(shape);
        });
    }

    /// <summary>
    /// we have this to handle a possible dragging element
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ListBowWithWrapPanel_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        var listBoxItem = sender as ListBoxItem;
        if (listBoxItem == null) return;
        _dragSource = listBoxItem.FindParent<ListBox>();
        _dragedData = listBoxItem.DataContext as Shape;
    }

    /// <summary>
    /// we have this to start the dragging process
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MouseMoveHandler(object sender, MouseEventArgs e)
    {
        if (_dragedData != null && _isInDrag == false)
        {
            _isInDrag = true;
            DragDrop.DoDragDrop(_dragSource, _dragedData, DragDropEffects.Move);
        }
    }

    /// <summary>
    /// we have this to handle the possible target position
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="dragEventArgs"></param>
    private void OnDragOver(object sender, DragEventArgs dragEventArgs)
    {
        var targetPlaceHolder = sender as ListBoxItem;
        if (targetPlaceHolder == null) return;
        _targetData = targetPlaceHolder.DataContext as Shape;
    }

    /// <summary>
    /// we have this to stop where there is no a dragging process
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void LeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        ResumeDragging();
    }

    /// <summary>
    /// we have this to perform the drop(insert the element into a new position)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ListBowWithWrapPanel_OnDrop(object sender, DragEventArgs e)
    {
        if (Equals(_dragedData, _targetData)) return;
        var targetPlaceHolder = sender as ListBoxItem;
        if (targetPlaceHolder == null) return;

        var removedIdx = _observableCollection.IndexOf(_dragedData);
        var targetIdx = _observableCollection.IndexOf(_targetData);

        if (removedIdx < targetIdx)
        {
            _observableCollection.Insert(targetIdx + 1, _dragedData);
            _observableCollection.RemoveAt(removedIdx);
        }
        else
        {
            int remIdx = removedIdx + 1;
            if (_observableCollection.Count + 1 > remIdx)
            {
                _observableCollection.Insert(targetIdx, _dragedData);
                _observableCollection.RemoveAt(remIdx);
            }
        }

        ResumeDragging();

    }

    private void ResumeDragging()
    {
        _isInDrag = false;
        _dragedData = null;
    }
}

Regards. 问候。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM