2015-09-16 14 views
6

ho ICollectionView sembracambiare il gruppo di elemento in ICollectionView

public ICollectionView UsersCollectionView 
{ 
    get 
    { 
     var view = CollectionViewSource.GetDefaultView(this); 
     view.GroupDescriptions.Add(new PropertyGroupDescription("SeriesName")); 
     view.SortDescriptions.Add(new SortDescription("CreationDate", ListSortDirection.Ascending)); 
     view.SortDescriptions.Add(new SortDescription("DocumentTypeId", ListSortDirection.Ascending)); 
     return view; 
    } 
} 

voglio usare il drag & drop per cambiare la voce Nome Series, e la posizione sulla lista visualizzare qualsiasi idea di come farlo, per esempio

--- ScienceFiction 
------------> Book1 
------------> Book2 
--- History 
------------> Book3 
------------> Book4 

se Idraged e droped Book3 in ScienceFiction l'uscita dovrebbe essere

--- ScienceFiction 
------------> Book1 
------------> Book2 
------------> Book3 
--- History 
------------> Book4 

Io uso il codice XAML in questo modo:

<UserControl.Resources> 
    <Style x:Key="ContainerStyle" TargetType="{x:Type GroupItem}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <Expander Header="{Binding Name}" IsExpanded="True"> 
         <ItemsPresenter /> 
        </Expander> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</UserControl.Resources> 
<Grid> 
    <ListBox x:Name="lbPersonList" Margin="19,17,162,25" AlternationCount="2" ItemsSource="{Binding}"> 
     <ListBox.GroupStyle> 
      <GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/> 
     </ListBox.GroupStyle> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Name}"/> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 

</Grid> 

risposta

2

AMH,

prima modificare lo stile ListViewItem. È il contenitore che contiene ogni riga (datatemplate instanciation) della listbox. È un buon posto per gestire Drag and Drop a livello di linea (non un controllo di una linea, ce ne potrebbero essere molti nel DataTemplate). In Visual Studio, selezionare la casella di riepilogo, fare clic destro, modificare i modelli aggiuntivi/Modifica elemento generato Container (ItemContainerStyle)/modificare una copia

Nel ListBoxItemStyle creato, aggiungere quei tre dichiarazioni tra i setter:

 <EventSetter Event="ListBoxItem.DragOver" Handler="ListBoxItemDragOver"/> 
     <EventSetter Event="ListBoxItem.Drop" Handler="ListBoxItemDrop"/> 
     <EventSetter Event="ListBoxItem.PreviewMouseMove" Handler="ListBoxItemPreviewMouseMove"/> 

Impostare la proprietà AllowDrop true sulla ListBox:

<ListBox x:Name="listboxBooks" AllowDrop="True"> 

quindi implementare i gestori del XAML.codice cs:

#region DnD management 

    private Book sourceBook; 
    private void ListBoxItemPreviewMouseMove(object sender, MouseEventArgs e) 
    { 
     if (e.LeftButton != MouseButtonState.Pressed) 
      return; 
     var listboxItem = sender as ListBoxItem; 
     if (listboxItem == null) 
      return; 
     sourceBook = listboxItem.DataContext as Book; 
     if (sourceBook == null) 
      return; 
     var data = new DataObject(); 
     data.SetData(sourceBook); 
     // provide some data for DnD in other applications (Word, ...) 
     data.SetData(DataFormats.StringFormat, sourceBook.ToString()); 
     DragDropEffects effect = DragDrop.DoDragDrop(listboxItem, data, DragDropEffects.Move | DragDropEffects.Copy); 
    } 
    private void ListBoxItemDrop(object sender, DragEventArgs e) 
    { 
     if (!e.Data.GetDataPresent(typeof(Book))) 
      return; 
     var listBoxItem = sender as ListBoxItem; 
     if (listBoxItem == null) 
      return; 
     var targetBook = listBoxItem.DataContext as Book; 
     if (targetBook != null) 
     { 
      viewModel.RecategorizeBook(sourceBook, targetBook.Category); 
     } 
     e.Handled = true; 
    } 
    private void ListBoxItemDragOver(object sender, DragEventArgs e) 
    { 
     Debug.WriteLine(e.Effects); 
     if (!e.Data.GetDataPresent(typeof(Book))) 
     { 
      e.Effects = DragDropEffects.None; 
      e.Handled = true; 
     } 
    } 
    private void GroupItemDrop(object sender, DragEventArgs e) 
    { 
     if (!e.Data.GetDataPresent(typeof(Book))) 
      return; 
     var groupItem = sender as GroupItem; 
     if (groupItem == null) 
      return; 
     dynamic targetGroup = groupItem.DataContext; 
     if (targetGroup != null) 
     { 
      // here I change the category of the book 
      // and refresh the view of the collectionViewSource (see link to project zipped further) 
      viewModel.RecategorizeBook(sourceBook, targetGroup.Name as String); 
     } 
     e.Handled = true; 
    } 
    #endregion 

Si noti che ho implementato anche Gestione delle interruzioni sull'intestazione del gruppo nei gestori. Così il gestore deve essere dichiarato nel GroupStyle XAML:

<ListBox.GroupStyle> 
    <GroupStyle> 
     <GroupStyle.ContainerStyle> 
      <Style TargetType="{x:Type GroupItem}"> 
       <EventSetter Event="GroupItem.Drop" Handler="GroupItemDrop"/> 
       <EventSetter Event="GroupItem.PreviewMouseMove" Handler="ListBoxItemPreviewMouseMove"/> 

Funziona, qui è un codice di lavoro pieno: http://1drv.ms/1FhBZwr

si desidera il miglior codice possibile

+0

@AMH, non è vero la risposta alla tua domanda? –

+0

AMH, ti aspetti qualcosa di più/diverso da assegnare la taglia? –

+0

Per chiunque intorno: sarebbe utile se mostrassi come inserire l'elemento rilasciato in una data posizione in un gruppo, non nel gruppo, ma in una posizione casuale? In questo modo l'utente finale sarebbe il padrone del gruppo. –

1

Purtroppo .net non fornisce ancora un "facile da usare" l'attuazione di drag'n'drop. Devi costruire un sacco di cose per conto tuo. Il punto di partenza sarà un Behavior che inizia il trascinamento e uno ContentControl è l'area sulla quale l'utente può rilasciare le cose. Avendo quelli definiti puoi facilmente riutilizzare questo concetto. Nell'esempio seguente, StackPanel può essere "trascinato" su un'area "invisibile" che circonda lo TextBlock. In questo modo puoi implementare manualmente i tuoi libri in ordine (rilasciati prima/dietro il libro sotto il puntatore del mouse).

Se si desidera eliminare i libri sulle intestazioni, circondarli con un DropArea. Potresti anche implementare entrambi i modi.

tuo XAML sarà simile:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
[...] 
<ListBox x:Name="lbPersonList" Margin="19,17,162,25" AlternationCount="2" ItemsSource="{Binding}"> 
    <ListBox.GroupStyle> 
     <GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/> 
    </ListBox.GroupStyle> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <StackPanel> 
       <myOwn:DropArea> 
        <TextBlock Text="{Binding Name}"/> 
       </myOwn:DropArea> 
       <i:Interaction.Behaviors> 
        <myOwn:DragBehavior/> 
       </i:Interaction.Behaviors> 
      </StackPanel> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Il DragBehavior sarà simile:

public class DragBehavior : Behavior<FrameworkElement> 
    [...] 
    protected override void OnAttached() 
    { 
     AssociatedObject.MouseMove += AssociatedObject_MouseMove; 
     AssociatedObject.MouseDown += AssociatedObject_MouseLeftButtonDown; 
     AssociatedObject.MouseLeave += AssociatedObject_MouseLeave; 
     base.OnAttached(); 
    } 
    protected override void OnDetaching() 
    { 
     AssociatedObject.MouseMove -= AssociatedObject_MouseMove; 
     AssociatedObject.MouseDown -= AssociatedObject_MouseLeftButtonDown; 
     AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave; 
     base.OnDetaching(); 
    } 
    protected virtual void AssociatedObject_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (some condition of mouse button states or mouse moves) 
     { 
       DataObject data = new DataObject(); 
       data.SetData(typeof(anyKeyType), anyData); 
       data.SetData(typeof(anyOtherKeyType), anyOtherData); 
       DragDrop.DoDragDrop(fe, data, DragDropEffects.Move);     
     } 
    } 

Il DropArea sarà simile:

public class DropArea : ContentControl 
    [...] 
    public DropArea() 
    { 
     DragEnter += AssociatedObjectDragEnter; 
     DragLeave += AssociatedObjectDragLeave; 
     DragOver += AssociatedObjectDragOver; 
     IsTabStop = false; 
     AllowDrop = true; 
    } 
    protected override void AssociatedObjectDrop(object sender, DragEventArgs e) 
    { 
     object o = e.Data.GetData(typeof(anyKeyType)); 
     //handle dropped data 
    } 

speranza che possa aiutare il vostro modo. Potrebbero esserci strutture o librerie per risolvere il problema, ma in questo modo puoi soddisfare le tue esigenze.

Problemi correlati