web-dev-qa-db-fra.com

WPF ListBoxItem double-cliquez sur?

Le WPF ListBox n’a pas d’événement DoubleClick, du moins pas à ce que je sache. Existe-t-il une solution de contournement pour ce problème qui me permettrait de double-cliquer sur un élément pour qu'un gestionnaire d'événements le fasse? Merci de votre aide.

29
David Veeneman

Vous pouvez toujours remplacer le modèle de contrôle ListItem et gérer l'événement de double-clic dans le modèle, par exemple dans une bordure invisible contenant le contenu normal du ListBox.

Cet article explique comment utiliser un ControlTemplate avec un ListBoxItem . Au-delà, ajoutez simplement le gestionnaire à l'élément le plus externe de votre modèle de contrôle.

Si vous avez Expression Blend, vous pouvez l'utiliser pour extraire le modèle de contrôle existant que vous souhaitez modifier afin que vous n'ayez pas à effectuer autant de travail pour vous assurer que la nouvelle zone de liste se comporte de la même manière que l'ancienne.

5
Ben Von Handorf

Il s'avère qu'il existe un événement MouseDoubleClick pour le contrôle ListBox. J'ai ajouté cet événement à mon contrôle ListBox et le gestionnaire d'événements l'a traitée, copiant l'élément sélectionné dans un autre contrôle ListBox. Donc, chaque fois que je double-clique sur un élément, il est copié.

34
David Veeneman

Il est possible de lier des commandes avec des paramètres à ListBoxItems sans utiliser code-behind ou comportements attachés, simplement en utilisant InputBindings avec un MouseBinding , comme indiqué précédemment dans cette réponse .

Exemple ListBox avec MouseBinding pour LeftDoubleClick:

<ListBox ItemsSource="{Binding MyDataSource}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding MySourceItemName}">
                <TextBlock.InputBindings>
                    <MouseBinding MouseAction="LeftDoubleClick"
                                  Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
                                  CommandParameter="{Binding MySourceItemId}" />
                </TextBlock.InputBindings>
            </TextBlock>
        </DataTemplate> 
    </ListBox.ItemTemplate>
</ListBox>

Si la commande est définie dans le même DataContext que le ItemsSource du ListBox, vous pouvez le lier en utilisant la liaison RelativeSource incluse dans l'exemple.

23
marapet

Si vous utilisez la liaison de données, alors ce problème est très facile à résoudre

<ListBox.ItemTemplate>
    <DataTemplate>
        <TextBlock Text="{Binding ObjectName}"
           MouseDown="TextBlock_MouseDown"/>
    </DataTemplate>
</ListBox.ItemTemplate>    

Puis dans votre code derrière, vérifiez s'il y a un double clic

private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.ClickCount>=2)
    { 
        ....
    }
}

Si votre élément double-cliqué n'a pas été sélectionné avant le double-clic, il n'apparaîtra pas sélectionné dans le gestionnaire d'événements. Votre logique au sein de ce gestionnaire doit en tenir compte

13
gls123

J'ai utilisé la réponse ci-dessus de David (qui commence par "Il s'avère qu'il existe un événement MouseDoubleClick pour le ListBox") pour générer une solution basée sur son approche mais implémentée avec un comportement attaché.

Je ne dis pas que vous n'aurez aucun code en retard parce que je sais qu'il y a des situations où il ne devrait pas être évité pour n'importe quel prix. Cependant, ceci est un autre exemple de la façon dont vous pouvez convertir une solution basée sur les événements en une solution compatible MVVM qui fonctionne via la conversion de liaison de commande d’événement à commande.

Ce code de comportement ci-joint:

using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;

/// <summary>
/// Class implements a <seealso cref="Selector"/> double click
/// to command binding attached behaviour.
/// </summary>
public class DoubleClickSelectorItem
{
  #region fields
  public static readonly DependencyProperty DoubleClickItemCommandProperty =
      DependencyProperty.RegisterAttached("DoubleClickItemCommand",
                                          typeof(ICommand),
                                          typeof(DoubleClickSelectorItem),
                                          new PropertyMetadata(null,
                                          DoubleClickSelectorItem.OnDoubleClickItemCommand));
  #endregion fields

  #region constructor
  /// <summary>
  /// Class constructor
  /// </summary>
  public DoubleClickSelectorItem()
  {

  }
  #endregion constructor

  #region properties
  #endregion properties

  #region methods
  #region attached dependency property methods
  public static ICommand GetDoubleClickItemCommand(DependencyObject obj)
  {
    return (ICommand)obj.GetValue(DoubleClickItemCommandProperty);
  }

  public static void SetDoubleClickItemCommand(DependencyObject obj, ICommand value)
  {
    obj.SetValue(DoubleClickItemCommandProperty, value);
  }
  #endregion attached dependency property methods

  private static void OnDoubleClickItemCommand(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    var uiElement = d as Selector;

    // Remove the handler if it exist to avoid memory leaks
    if (uiElement != null)
      uiElement.MouseDoubleClick -= UIElement_MouseDoubleClick;

    var command = e.NewValue as ICommand;
    if (command != null)
    {
      // the property is attached so we attach the Drop event handler
      uiElement.MouseDoubleClick += UIElement_MouseDoubleClick;
    }
  }

  private static void UIElement_MouseDoubleClick(object sender, MouseButtonEventArgs e)
  {
    var uiElement = sender as Selector;

    // Sanity check just in case this was somehow send by something else
    if (uiElement == null)
      return;

    // Is there a selected item that was double clicked?
    if (uiElement.SelectedIndex == -1)
      return;

    ICommand doubleclickCommand = DoubleClickSelectorItem.GetDoubleClickItemCommand(uiElement);

    // There may not be a command bound to this after all
    if (doubleclickCommand == null)
      return;

    // Check whether this attached behaviour is bound to a RoutedCommand
    if (doubleclickCommand is RoutedCommand)
    {
      // Execute the routed command
      (doubleclickCommand as RoutedCommand).Execute(uiElement.SelectedItem, uiElement);
    }
    else
    {
      // Execute the Command as bound delegate
      doubleclickCommand.Execute(uiElement.SelectedItem);
    }            
  }
  #endregion methods
}

Utilisation en XAML:

<ListBox ItemsSource="{Binding CurrentItems}"
         behav:DoubleClickSelectorItem.DoubleClickItemCommand="{Binding Path=NavigateDownCommand}"
         />
3
user3313608

Le ListBox a maintenant un double-clic.

1
Travis Banger

Sur l'événement de double-clic, utilisez: 

if (e.OriginalSource.GetType().ToString() == "System.Windows.Controls.TextBlock")
     DoubleClickDoneOnItem(); 
0
Grunwaldt