2016-04-15 2 views
2

Я создаю customcontrol динамически внутри оболочки. Теперь мне нужно изменить порядок пользовательских элементов управления, которые находятся внутри оболочки. Возможно ли переупорядочить пользовательские элементы управления внутри оберточной панели с помощью перетаскивания?Переставить CustomControl внутри wrappanel в wpf C#

Вот мой 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> 

Я попытался поставить панель обертку внутри списка, как это было предложено в данном ответе (ответ Илана), и теперь моя панель не доступна в код позади. AM я делаю что-то неправильно?

enter image description here

ответ

1

Попробуйте поместить свои элементы в ItemsControl и установить WrapPanel быть ItemsPanel контроля, то просто изменить порядок элементов управления внутри элемента управления элементов. Вот простой пример (введите свой контроль в InputCollection).

Update # 2 - DragAndDrop

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> 

код-за (возможно, пример перетаскивания)

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; 
    } 
} 

С уважением.

+0

Я держал обруча панели внутри элемента управления элемента, как вы said.But теперь панель не была доступна в коде позади :(почему его так? – Arshad

+0

@dahsra зачем вам это нужно, чтобы быть доступным? Пожалуйста, держите в вашем уме, что вы добавляете элементы в ItemsControl, а затем они входят в оболочку. – Ilan

+0

Теперь я динамически создаю пользовательский контроль внутри этой панели обертки в коде позади, теперь вам нужно, чтобы я создал элементы управления внутри Itemscontrol uh ?? – Arshad

2

Drag Drop in a WrapPanel

Здесь я показал Buttons, вы можете изменить его для ваших нужд.

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> 

Код

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); 
} 

Другой подход с использованием 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); 
}