2010-07-16 3 views
5

J'ai un objet listview contenant des fichiers dans le programme. Le comportement listview par défaut me permet de faire toutes les opérations de sélection de la liste (cliquez + Maj pour sélectionner un bloc, cliquez sur + ctrl pour sélectionner individuellement les membres d'un groupe d'éléments, et cliquez pour sélectionner un seul élément). Je veux commencer à faire glisser ces éléments avec un clic du bouton gauche de la souris, mais il désélectionne les éléments ... et même lorsque la souris se déplace, elle sélectionne la souris. Comment gérer les événements de la souris pour permettre la sélection par défaut normalement, mais pas sélectionner/désélectionner si l'élément est déplacé? Si je gère l'événement de clic vers le bas, le changement de sélection se produit en même temps ... c'est seulement quand un drag commence alors que le clic est encore bas que je sais qu'il s'agit d'un glisser-déposer contre un changement de sélection.WPF listview glisser sans désélection

Voici le XAML de base pour le contrôle ...

<Window.Resources> 
    <Style x:Key="itemstyle" TargetType="{x:Type ListViewItem}"> 
     <EventSetter Event="PreviewMouseDown" Handler='listView2_MouseLeftButtonDown'/> 
    </Style> 
</Window.Resources> 


<ListView Grid.Column="0" Grid.Row="1" Name="listView2" Margin="5,5,5,5" BorderBrush="LightGray" AllowDrop="True" Drop="listView2_Drop" ItemsSource="{Binding}" ItemContainerStyle="{StaticResource itemstyle}"> 
       <ListView.View> 
        <GridView> 
         <GridViewColumn Header="Name" Width="100"> 
          <GridViewColumn.CellTemplate> 
           <DataTemplate> 
            <StackPanel Orientation="Horizontal"> 
             <Image Source="{Binding Bmp}"/> 
             <TextBlock Text="{Binding Name}"/> 
            </StackPanel> 
           </DataTemplate> 
          </GridViewColumn.CellTemplate> 
         </GridViewColumn> 
         <GridViewColumn Header="Ext" DisplayMemberBinding="{Binding Ext}" Width="Auto"/> 
         <GridViewColumn Header="Size" DisplayMemberBinding="{Binding Size}" Width="Auto"/> 
         <GridViewColumn Header="Date" DisplayMemberBinding="{Binding Date}" Width="Auto"/> 
        </GridView> 
       </ListView.View> 
      </ListView> 

Ok, donc je suis allé avec les événements de la manipulation de la souris et PreviewMouseDown aperçu jusqu'à ... si une touche de commande ou changement la touche est enfoncée, je ne mets pas le drapeau handle ... mais sinon je mets l'argument managé à true (donc les changements de sélection ne se produisent pas) Puis sur l'évènement previewmouseup, je complète la sélection en sélectionnant le "selected" valeur à true (à nouveau uniquement lorsque shift ou Ctrl est enfoncé). Donc, cela fonctionne un peu ... mais le shift-block-selection n'utilise aucun élément que je sélectionne par programme comme point de départ valide pour le select, mais je vais plutôt le premier élément cliqué avec une touche shift ou ctrl (même si J'ai effacé tous les éléments sélectionnés manuellement).

Voici la source:

private void listView2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     if (e.LeftButton == MouseButtonState.Pressed) 
     { 
      if (!Keyboard.IsKeyDown(Key.LeftCtrl) && 
       !Keyboard.IsKeyDown(Key.RightCtrl) && 
       !Keyboard.IsKeyDown(Key.LeftShift) && 
       !Keyboard.IsKeyDown(Key.RightShift)) 
      { 
       e.Handled = true; 
      } 
     } 
    } 

    private void listView2_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
    { 
     if (e.ChangedButton == MouseButton.Left) 
     { 
      if (!Keyboard.IsKeyDown(Key.LeftCtrl) && 
       !Keyboard.IsKeyDown(Key.RightCtrl) && 
       !Keyboard.IsKeyDown(Key.LeftShift) && 
       !Keyboard.IsKeyDown(Key.RightShift)) 
      { 

       listView2.SelectedItems.Clear(); 
       ListViewItem lvi = sender as ListViewItem; 
       listView2.SelectedItem = lvi; 
       lvi.IsSelected = true; 
       e.Handled = true; 
      } 
     } 
    } 

Répondre

0

eu le même problème avec le contrôle il n'y a pas longtemps TreeView ... voici comment je travaillais autour de la question:

private void TreeViewItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    // skip mouse clicks on the expander button 
    if (e.Source is ToggleButton) 
     return; 

    // find the original source's parent TreeViewItem 
    DependencyObject originalSource = e.OriginalSource as DependencyObject; 
    while (originalSource != null) 
    { 
     TreeViewItem tvi = originalSource as TreeViewItem; 
     if (tvi != null) 
     { 
      IListItem listItem = tvi.Header as IListItem; 
      if (listItem != null) 
      { 
       if (Keyboard.Modifiers == ModifierKeys.Shift) 
        ViewModel.MultiSelectTo(listItem); 
       else if (Keyboard.Modifiers == ModifierKeys.Control) 
        ViewModel.ToggleSelection(listItem); 
       else 
        ViewModel.Select(listItem); 
      } 

      // the TreeViewItem is never truly selected... when selected, we manually change it's background color (see xaml) 
      tvi.IsSelected = false; 
      e.Handled = true; 
      break; 
     } 

     originalSource = VisualTreeHelper.GetParent(originalSource); 
    } 
} 

XAML:

<Style.Triggers> 
<DataTrigger Binding="{Binding Selected}" Value="True"> 
    <Setter Property="Background" Value="#FF3399FF" /> 
</DataTrigger> 
</Style.Triggers> 


Le IListItem interface est l'interface que mes objets de données implémente afin d'être montré dans mon TreeView. La propriété ViewModel est ma vue DataContext. En outre, le commentaire suivant est important "le TreeViewItem n'est jamais vraiment sélectionné ... lorsqu'il est sélectionné, nous changeons manuellement sa couleur d'arrière-plan (voir xaml)".

Donc, fondamentalement, ce que j'ai fait, c'est supprimer la gestion de la sélection du contrôle TreeView pour le gérer moi-même.

Espérons que cela aide de quelque façon que ce soit ...