example - wpf layout
WPF ListBoxItem doble clic? (7)
El WPF ListBox no tiene un evento DoubleClick, al menos no por lo que puedo decir. ¿Hay una solución para este problema que me permita hacer doble clic en un elemento para que un controlador de eventos haga algo con él? Gracias por tu ayuda.
El cuadro de lista tiene un evento de doble clic ahora.
En el evento de doble clic use:
if (e.OriginalSource.GetType().ToString() == "System.Windows.Controls.TextBlock")
DoubleClickDoneOnItem();
Es posible vincular comandos con parámetros a ListBoxItem
s sin usar comportamientos de código subyacente o adjuntos , simplemente usando InputBindings
con un MouseBinding
, como se muestra anteriormente en esta respuesta .
Ejemplo ListBox
con MouseBinding
para 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 el comando está definido en el mismo DataContext que el ItemsSource
del ListBox
, se puede enlazar usando el enlace RelativeSource
como se incluye en el ejemplo.
He utilizado la respuesta anterior de David (que comienza con ''Resulta que hay un evento MouseDoubleClick para el ListBox'') para generar una solución que se basa en su enfoque pero se implementa con un comportamiento adjunto.
No estoy diciendo que no tenga ningún código detrás porque sé que hay situaciones en las que no debe evitarse por ningún precio. Pero, este es otro ejemplo de cómo puede convertir una solución basada en eventos en una solución compatible con MVVM que funciona a través de Evento a comando de conversión de enlace.
Este es mi código de comportamiento adjunto:
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
}
Uso en XAML:
<ListBox ItemsSource="{Binding CurrentItems}"
behav:DoubleClickSelectorItem.DoubleClickItemCommand="{Binding Path=NavigateDownCommand}"
/>
Resulta que hay un evento MouseDoubleClick para ListBox. Agregué este evento a mi ListBox e hice que el controlador del evento procesara mi tarea, copiando el elemento seleccionado a otro ListBox. Entonces, cada vez que hago doble clic en un elemento, se copia.
Si está utilizando el enlace de datos, este problema es muy fácil de resolver.
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ObjectName}"
MouseDown="TextBlock_MouseDown"/>
</DataTemplate>
</ListBox.ItemTemplate>
Luego, en su código, revise si hace doble clic de la siguiente manera
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount>=2)
{
....
}
}
Si su elemento de doble clic no se seleccionó antes del doble clic, entonces no aparecerá seleccionado en el controlador de eventos. Tu lógica dentro de ese manejador debe tener esto en cuenta
Siempre se puede anular la plantilla de control ListItem y controlar el evento de doble clic dentro de la plantilla, por ejemplo, en un borde invisible que contiene el contenido normal de ListBox.
Este artículo le muestra cómo usar un ControlTemplate con un ListBoxItem . Más allá de eso, simplemente agregue el controlador al elemento más externo de su plantilla de control.
Si tiene Expression Blend, puede usarlo para extraer la plantilla de control existente para que la modifique, de modo que no tenga que hacer tanto trabajo para asegurarse de que el nuevo cuadro de lista se comporte igual que el anterior.