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.
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.
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é.
Il est possible de lier des commandes avec des paramètres à ListBoxItem
s 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.
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
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}"
/>
Le ListBox a maintenant un double-clic.
Sur l'événement de double-clic, utilisez:
if (e.OriginalSource.GetType().ToString() == "System.Windows.Controls.TextBlock")
DoubleClickDoneOnItem();