2010-07-16 16 views
5

Tengo un objeto listview que contiene archivos en el programa. El comportamiento predeterminado de la vista de lista me permite hacer todas las operaciones de selección en la lista (haga clic en + shift para seleccionar un bloque, haga clic en + ctrl para seleccionar individualmente miembros de un grupo de elementos y haga clic para seleccionar un solo elemento).lista de WPF arrastre sin anular la selección

Quiero comenzar a arrastrar estos elementos haciendo clic y manteniendo presionado el botón izquierdo del mouse, pero anula la selección de los elementos ... e incluso cuando el mouse se mueve, seleccionará el mouse que sea. ¿Cómo manejo los eventos del mouse para permitir la selección predeterminada normalmente, pero no seleccionar/deseleccionar si el elemento está siendo arrastrado?

Si manejo el evento de clic hacia abajo, el cambio de selección ocurre al mismo tiempo ... es solo cuando se inicia una acción de arrastre mientras el clic aún está abajo que sé que es un arrastrar y soltar versus un cambio de selección.

Aquí es el XAML básica para el control ...

<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, por lo que he pasado con el manejo de la PreviewMouseDown y la vista previa del ratón hacia arriba eventos ... si una clave de control o cambio se presiona la tecla, no configuro la bandera del mango ... pero de lo contrario configuro el argumento manejado en verdadero (para que los cambios de selección no ocurran) Luego, en el evento previewmouseup, completo la selección individual configurando el "seleccionado" value to true (otra vez solo cuando se presiona shift o ctrl). Así que esto funciona ... pero la selección de bloque de cambios no usa ningún elemento que seleccione programáticamente como un punto de inicio válido para la selección, sino que va al primer elemento al que se presiona usando una tecla shift o ctrl (incluso si yo ' ha borrado todos los elementos seleccionados manualmente).

Aquí está la fuente:

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

Respuesta

0

Tenía el mismo problema con el control de TreeView no hace mucho ... así es como he trabajado en torno al tema:

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> 


ElLa interfazes la interfaz que implementan mis objetos de datos para mostrarse en mi TreeView. La propiedad ViewModel es mi opinión DataContext. Además, el siguiente comentario es importante: "TreeViewItem nunca se selecciona verdaderamente ... cuando se selecciona, manualmente cambiamos el color de fondo (consulte xaml)".

Así que, básicamente, lo que hice, es eliminar el manejo de la selección del control TreeView para manejarlo yo mismo.

Espero que esto ayude de alguna manera ...

Cuestiones relacionadas