2010-08-20 40 views
11

Tengo un ItemsControl con un DataTemplate que está vinculado a un ObservableCollection de enteros.ItemsControl Arrastrar y soltar

<ItemsControl Name="DimsContainer" ItemTemplate="{StaticResource DimensionsTemplate}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <StackPanel Orientation="Horizontal"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

Y en los Recursos de Windows:

<Window.Resources> 
    <DataTemplate x:Key="DimensionsTemplate" > 
     <TextBlock Text="{Binding}" 
         Padding="5" 
         VerticalAlignment="Center" 
         FontSize="32"/> 
    </DataTemplate> 
</Window.Resources> 

Estoy tratando de poner en práctica la capacidad de arrastrar y soltar elementos en el ItemsControl (es decir, para poder cambiar el orden de los números enteros). ¿Alguien tiene un ejemplo simple de cómo hacer esto? Conecté los eventos PreviewMouseMove, DragEnter y Drop. El problema es que no puedo encontrar la manera de determinar qué elemento se está arrastrando y dónde se arrastra. Parece que todo el ItemsControl pasa a los eventos.

+0

Hola. Veo el enlace provisto por @ Golbin. Pero el ejemplo es sobre drogas y droping entre 2 panel. De hecho, quiero reordenar en UNO 'ItemsControl' como usted. ¿Puedes ayudarme por favor? ¿Puedes poner tu código de solución aquí? ¿O puede sugerirme alguna orientación, por favor? Gracias por adelantado. –

+0

@ king.net ¿Todavía necesita el ejemplo relacionado con este problema? aquí hay uno relacionado con el listbox - http://stackoverflow.com/questions/36642622/rearrange-customcontrol-inside-wrappanel-in-wpf-c-sharp. Si necesita puedo intentar adaptar esto para la plantilla de datos ... – Ilan

Respuesta

5

Aquí hay un ejemplo de cómo lo he hecho.

XAML:

<Window.DataContext> 
    <local:MyViewModel /> 
</Window.DataContext> 

<Grid> 
    <ScrollViewer> 
     <ListView ItemsSource="{Binding MyData}" HorizontalAlignment="Stretch" Name="listview" ScrollViewer.PanningMode="VerticalOnly"> 
      <ListView.ItemTemplate> 
       <DataTemplate> 
        <Button Content="{Binding}" 
         Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}" 
         CommandParameter="{Binding}" 
         Margin="5 2" Width="150" Height="50" 
         FontSize="30" /> 
       </DataTemplate> 
      </ListView.ItemTemplate> 
      <ListView.Resources> 
       <Style TargetType="Button"> 
        <EventSetter Event="PreviewMouseMove" Handler="PreviewMouseMove" />       
        <EventSetter Event="Drop" Handler="Drop" />      
        <Setter Property="AllowDrop" Value="True" />       
       </Style> 
      </ListView.Resources> 
     </ListView> 
    </ScrollViewer> 
</Grid> 

modelo de vista:

class MyViewModel 
{ 
    public MyViewModel() 
    { 
     MyCommand = new ICommandImplementation(); 
    } 

    public ObservableCollection<string> MyData 
    { 
     get 
     { 
      return new ObservableCollection<string>(new string[]{ 
      "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", 
      "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty" 
      }); 
     } 
    } 

    public ICommand MyCommand { get; private set; } 

    private class ICommandImplementation : ICommand 
    { 
     public bool CanExecute(object parameter) { return true; } 
     public event EventHandler CanExecuteChanged; 
     public void Execute(object parameter) { System.Windows.MessageBox.Show("Button clicked! " + (parameter ?? "").ToString()); } 
    } 
} 

Incluso TS:

private void Drop(object sender, DragEventArgs e) 
    { 
     var source = e.Data.GetData("Source") as string; 
     if (source != null) 
     { 
      int newIndex = listview.Items.IndexOf((sender as Button).Content); 
      var list = listview.ItemsSource as ObservableCollection<string>; 
      list.RemoveAt(list.IndexOf(source)); 
      list.Insert(newIndex, source); 
     } 
    } 

    private void PreviewMouseMove(object sender, MouseEventArgs e) 
    { 
     if (e.LeftButton == MouseButtonState.Pressed) 
     { 
      Task.Factory.StartNew(new Action(() => 
       { 
        Thread.Sleep(500); 
        App.Current.Dispatcher.BeginInvoke(new Action(() => 
         { 
          if (e.LeftButton == MouseButtonState.Pressed) 
          {          
           var data = new DataObject(); 
           data.SetData("Source", (sender as Button).Content); 
           DragDrop.DoDragDrop(sender as DependencyObject, data, DragDropEffects.Move); 
           e.Handled = true; 
          } 
         }), null); 
       }), CancellationToken.None); 
     }   
    } 

El ejemplo de arriba es un poco más compleja causa cada artículo de list es un Button y en Buttonclick que también tienen que hacer algún tipo de acción. Su caso es relativamente fácil.

Arrastrar & La caída puede ser confusa para muchos desarrolladores. Pero por debajo de los son algunos puntos clave de cómo hacerlo:

  1. Uso PreviewMouseMove evento para iniciar realmente un lastre y en el uso manipulador DragDrop.DoDragDrop evento para recaudar DragDrop relacionados eventos y Cursors. sender argumento es el elemento que tiene capturado el mouse actualmente en este caso UIElement que es que se está arrastrando.

  2. Uso DragEnter & DragOver evento si desea cambiar la visual del elemento sobre el cual el Mouse está arrastrando actualmente. sender argumento es el elemento que se ha arrastrado actualmente/que acaba de finalizó el arrastre sobre la situación.

  3. Utilice Drop evento para controlar el elemento caído. El argumento sender es el elemento sobre el que ocurrió el Gota.

  4. Utilice DataObject objeto para pasar información entre estos eventos. SetData método de la clase se utiliza para agregar datos en esto.Este método tiene dos argumentos, y funcionan como key-value par. Una vez configurado, puede obtener estos datos en el siguiente evento llamado DragDrop utilizando el método GetData pasando el key como argumento. (Es decir e.Data.GetData("Source"))

Here es un puesto relativa.

+0

Gracias por esto, Kylo. Estaba buscando una implementación de arrastrar y soltar más simple de usar y su publicación me dio todas las pistas que necesitaba para hacerlo funcionar en mi aplicación. –

+0

@HDL_CinC_Dragon eres bienvenido :) –