WPF ListBoxItem 双击?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2547442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:38:11  来源:igfitidea点击:

WPF ListBoxItem double-click?

wpfwpf-controls

提问by David Veeneman

The WPF ListBox doesn't have a DoubleClick event, at least not as far as I can tell. Is there a workaround for this issue that would let me double-click on an item to have an event handler do something with it? Thanks for your help.

WPF ListBox 没有 DoubleClick 事件,至少据我所知没有。是否有解决此问题的方法可以让我双击一个项目让事件处理程序对其进行处理?谢谢你的帮助。

采纳答案by Ben Von Handorf

You could always override the ListItem Control Template and handle the double click event inside the template, for example in an invisible border that contains the normal contents of the ListBox.

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

This article shows you how to use a ControlTemplate with a ListBoxItem. Beyond that, simply add the handler to the outermost element of your control template.

本文向您展示了如何将 ControlTemplate 与 ListBoxItem 一起使用。除此之外,只需将处理程序添加到控件模板的最外层元素。

If you have Expression Blend, you can use it to extract the existing control template for you to modify so that you do not have to do as much work to ensure that the new list box behaves the same as the old.

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

回答by David Veeneman

It turns out there is a MouseDoubleClick event for the ListBox. I added this event to my ListBox and had the event handler process my task, copying the selected item to another ListBox. So, now whenever I double-click on an item, it gets copied.

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

回答by marapet

It is possible to bind commands with parameters to ListBoxItems without using code-behindor attached behaviors, simply by using InputBindingswith a MouseBinding, as shown before in this answer.

可以将带有参数的命令绑定到ListBoxItems 而不使用代码隐藏附加行为,只需使用InputBindingsa 即可MouseBinding,如本答案中所示。

Example ListBoxwith MouseBindingfor LeftDoubleClick:

例如ListBoxMouseBindingLeftDoubleClick

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

If the command is defined in the same DataContext as the ItemsSourceof the ListBox, it can be bound by using the RelativeSourcebinding as included in the example.

如果该命令是在相同的DataContext作为限定ItemsSourceListBox,它可以通过使用结合RelativeSource作为包括在例如结合。

回答by gls123

If you are using databinding, then this problem is very easy to solve

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

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

Then in your code behind, check for a double click as follows

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

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

If your double clicked item was not selected before the double click, then it wont appear selected in the event handler. Your logic within that handler needs to bear this in mind

如果在双击之前没有选择您的双击项目,则它不会在事件处理程序中显示为选中状态。您在该处理程序中的逻辑需要牢记这一点

回答by user3313608

I have used the above answer from David (which starts with 'It turns out there is a MouseDoubleClick event for the ListBox.') to generate a solution that is based on his approach but is implemented with an attached behavior.

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

I am not saying you shall not have any code behind because I know there are situations where it should not be avoided for any price. But, this is yet another example of how you can convert an event based solution into an MVVM compliant solution that works via Event to command binding conversion.

我并不是说你不应该有任何代码,因为我知道在某些情况下不应该以任何代价避免它。但是,这是如何将基于事件的解决方案转换为通过事件到命令绑定转换工作的 MVVM 兼容解决方案的另一个示例。

This my attached behavior code:

这是我附加的行为代码:

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
}

Usage in XAML:

XAML 中的用法:

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

回答by Travis Banger

The ListBox has a double click event now.

ListBox 现在有一个双击事件。

回答by Grunwaldt

On the double-click event use:

在双击事件上使用:

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