WPF ListBoxItem双击?

时间:2010-03-30 18:01:54

标签: wpf wpf-controls

WPF ListBox没有DoubleClick事件,至少没有我能说的那么多。是否有针对此问题的解决方法,让我双击项目以让事件处理程序对其执行某些操作?谢谢你的帮助。

9 个答案:

答案 0 :(得分:34)

事实证明,ListBox有一个MouseDoubleClick事件。我将此事件添加到我的ListBox并让事件处理程序处理我的任务,将所选项目复制到另一个ListBox。所以,现在每当我双击某个项目时,它就会被复制。

答案 1 :(得分:26)

可以将带有参数的命令绑定到ListBoxItem,而无需使用代码隐藏附加行为,只需使用InputBindings即可MouseBinding,如this answer中所示。

ListBox的{​​{1}}示例MouseBinding

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> 的{​​{1}}相同的DataContext中定义,则可以使用示例中包含的ItemsSource绑定对其进行绑定。

答案 2 :(得分:13)

如果您正在使用数据绑定,那么这个问题很容易解决

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

然后在您的代码中,检查双击如下

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

如果在双击之前未选中双击项目,则在事件处理程序中不会显示它。你在那个处理程序中的逻辑需要牢记这一点

答案 3 :(得分:5)

您可以始终覆盖ListItem控件模板并处理模板内的双击事件,例如在包含ListBox正常内容的不可见边框中。

This article shows you how to use a ControlTemplate with a ListBoxItem。除此之外,只需将处理程序添加到控件模板的最外层元素即可。

如果您有Expression Blend,您可以使用它来提取现有的控件模板以供您修改,这样您就不必做太多工作来确保新列表框的行为与旧列表框相同。

答案 4 :(得分:3)

我使用了David的上述答案(以“事实证明ListBox有一个MouseDoubleClick事件”开头)来生成一个基于他的方法的解决方案,但是使用附加行为实现。

我并不是说你不会有任何代码,因为我知道有些情况下不应该以任何代价来避免。但是,这是另一个如何将基于事件的解决方案转换为符合MVVM的解决方案的示例,该解决方案通过事件进行命令绑定转换。

这是我附加的行为代码:

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
}

XAML中的用法:

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

答案 5 :(得分:1)

ListBox现在有一个双击事件。

答案 6 :(得分:0)

在双击事件上使用:

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

答案 7 :(得分:0)

根据MSDN article,您可以按如下所示将处理程序添加到列表框中的每个项目:

<ListBox>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_MouseDoubleClick"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

然后在后面的代码中处理双击。然后,您可以通过处理程序中的DataContext来访问sender.DataContext。由于双击会选择一个项目,因此您还可以在SelectedItem上使用ListBox属性或类似属性。

我个人更希望使用Behavior解决方案,该解决方案允许重定向到命令,但是我不确定如何实现。

答案 8 :(得分:0)

由于我使用的是 SelectionMode="Multiple",因此当前的所有答案都不适用于我,所以我只想与您分享我发现的实现此功能的最简洁的方法。

首先,我为包含的 ListBoxItem 创建了一个处理程序:

public void listBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    ListBoxItem clickedItem = ((ListBoxItem)sender);
            
    for (int i = 0; i < listBox.Items.Count; i++)
    {
        if (listBoxECIRatioSizeAutoSelect.Items[i] == clickedItem)
        {
            doStuff(i);
            break;
        }
    }
}

然后,每当 ListBoxItem 添加到 ListBox 时,Handler 就会添加到 ListBoxItem:

private void addItemToListBox(string strItem)
{
    ListBoxItem newItem = new ListBoxItem();
    newItem.Content = strItem;
    newItem.MouseDoubleClick += listBoxItem_MouseDoubleClick;
    listBox.Items.Add(newItem);
}