C# Listview MouseDoubleClickEvent在后台代码中创建

C# Listview MouseDoubleClickEvent在后台代码中创建,c#,wpf,listview,code-behind,C#,Wpf,Listview,Code Behind,当我有: <UserControl.Resources> <Style x:Key="itemstyle" TargetType="{x:Type ListViewItem}"> <EventSetter Event="MouseDoubleClick" Handler="HandleDoubleClick" /> <Setter Property="HorizontalContentAlignment" Val

当我有:

<UserControl.Resources>

    <Style x:Key="itemstyle" TargetType="{x:Type ListViewItem}">
        <EventSetter Event="MouseDoubleClick" Handler="HandleDoubleClick" />
        <Setter Property="HorizontalContentAlignment" Value="Center" />
    </Style>
</UserControl.Resources>
<Grid>
    <ListView  ItemContainerStyle="itemstyle"  Name="listView1" >
        <ListView.View>
             <GridView>
                  ... etc
一切都很好。


现在我需要对代码隐藏做同样的事情。这就是我得出的结论:

 public Constructor(){

    listview.AddHandler(
        ListViewItem.MouseDoubleClickEvent, 
        new MouseButtonEventHandler(HandleDoubleClick)
    );
 }


 protected void HandleDoubleClick(object sender, MouseButtonEventArgs e)
 {
        T item = (T)(((ListViewItem)sender).Content);       
        // error cause the sender is the listview                           
 }

当我双击listview的任何部分而不仅仅是listviewItem时,会触发该事件。另外,我希望发件人是ListViewItem,而不是。发送方实际上是listview。我尝试过的事情:

1) 因为发件人是listview,所以我尝试将事件创建为:

我得到了相同的错误,发送者是listview

2) 而不是做:

我有:

问题是,如果用户双击listview中非该行的任何内容,它将返回当前选定的项目


为什么我的代码不起作用?我做错了什么?

在xaml中,将事件处理程序附加到ListViewItem,而在代码隐藏中,将其附加到ListView本身。这就是为什么你会有不同的行为。如果要在代码隐藏中执行相同的操作,则必须循环items集合中的所有项,并将每个项的双击事件绑定到处理程序


如果没有真正的理由在代码隐藏中这样做,我会选择更适合MVVM模式的xaml方法,您可以尝试在代码隐藏中保留尽可能少的代码。

在xaml中,您将事件处理程序附加到ListViewItem,而在代码隐藏中,您将其附加到ListView本身。这就是为什么你会有不同的行为。如果要在代码隐藏中执行相同的操作,则必须循环items集合中的所有项,并将每个项的双击事件绑定到处理程序


如果没有真正的理由在代码隐藏中这样做,我会选择更适合MVVM模式的xaml方法,您可以尝试在代码隐藏中保留尽可能少的代码。

不明白为什么要在代码隐藏中这样做,除非您希望在UserControl中包含命名内容,所以您要将其更改为自定义控件。尝试在代码隐藏中重复xaml代码,即为ListViewItem创建一个样式,并将其设置为listview的ItemContainerStyle。

不明白为什么要在代码隐藏中执行此操作,除非您希望UserControl中包含命名内容,所以要将其更改为自定义控件。尝试在代码隐藏中重复xaml代码,即为ListViewItem创建样式,并将其设置为listview的ItemContainerStyle


我认为你应该使用依附行为,因为

  • MVVM♥ 依附行为
  • 它是可重用的:一旦创建了用于双击的附加行为和命令,就可以将其附加到任何其他控件类型(因此可以使用相同的代码双击图像等)
  • 抽象脏的实现,因此xaml和视图模型都更加清晰
  • 他们的工作方式很棒,我喜欢使用聪明的代码
  • 以下是你要做的:


    创建ListViewItemDoubleClickCommandBehavior 如上图所示,这个
    CommandBehavior
    类将命令链接到控件

    • 在上面的例子中,它是一个按钮库,但我们要制作一个ListViewItem

    • 这一个需要prism,因为它继承的CommandBehaviorBase是该库的一部分。您可以全部获得(但对于本例,您只需要使用Prism.dll命令)

    • 命名约定要求您应以以下格式命名此CommandBehavior

       [X][Y]CommandBehavior
      
      X—将命令绑定到的控件的名称(在本例中为ListViewItem)
      Y-用户执行的导致命令发生的操作(在本例中,双击)

    代码如下:

        public class ListViewItemDoubleClickCommandBehaviour : CommandBehaviorBase<ListViewItem>
        {
            public ListViewItemDoubleClickCommandBehaviour(ListViewItem controlToWhomWeBind)
            : base(controlToWhomWeBind)
            {
                controlToWhomWeBind.MouseDoubleClick += OnDoubleClick;
            }
    
            private void OnDoubleClick(object sender, System.Windows.RoutedEventArgs e)
            {
    
                ExecuteCommand();
    
            }
        }
    
    注: 我知道这看起来像是很多复杂的代码,但一旦您足够频繁地使用它,它就是一个简单的模式,它将所有的复杂性从视图模型中抽象出来,因此命令到控件的绑定看起来非常简单


    在viewmodel中创建命令,并在xaml中绑定到该命令 现在繁重的工作结束了,我们做简单的部分

    创建命令

    我假设您熟悉命令,您可以像往常一样创建命令:

        public ICommand DisplaySelectedItemCmd { get; protected set; }
    
        //This method goes in your constructor
        private void InitializeCommands()
        {
            //Initializes the command
            this.DisplaySelectedItemCmd = new RelayCommand(
                (param) =>
                {
                    this.DisplaySelectedItem((object)param);
                },
                (param) => { return this.CanDisplaySelectedItem; }
            );
        }      
        //The parameter should be your listview's selected item. I have no idea what type it is so I made it an object
        public void DisplaySelectedPolicy(object selectedListViewItem)
        {
            //Code to perform when item is double clicked
        }
    
        private bool CanDisplaySelectedPolicy
        {
            get
            {
                return true; //Change this bool if you have any reason to disable the double clicking, as this bool basically is linked to the double click command firing.
            }
        }
    
    在xaml中创建绑定

    现在来看精彩的部分。 首先添加xml名称空间:

     xmlns:commands="clr-namespace:CommandHandling" 
    
    然后在ListViewItem上绑定

     <Style TargetType="{x:Type ListViewItem}" x:Key="{x:Type ListViewItem}" >
           <Setter Property="commands:DoubleClick.Command" Value="{Binding Path=bleh}"/>
     </Style>
    
    
    
    完成了

    如果这不起作用,请告诉我。(将来读到这篇文章的人,如果你愿意,可以向我寻求帮助)

    u_


    我认为你应该使用依附行为,因为

  • MVVM♥ 依附行为
  • 它是可重用的:一旦创建了用于双击的附加行为和命令,就可以将其附加到任何其他控件类型(因此可以使用相同的代码双击图像等)
  • 抽象脏的实现,因此xaml和视图模型都更加清晰
  • 他们的工作方式很棒,我喜欢使用聪明的代码
  • 以下是你要做的:


    创建ListViewItemDoubleClickCommandBehavior 如上图所示,这个
    CommandBehavior
    类将命令链接到控件

    • 在上面的例子中,它是一个按钮库,但我们要制作一个ListViewItem

    • 这一个需要prism,因为它继承的CommandBehaviorBase是该库的一部分。您可以全部获得(但对于本例,您只需要使用Prism.dll命令)

    • 命名约定要求您应以以下格式命名此CommandBehavior

       [X][Y]CommandBehavior
      
      X—将命令绑定到的控件的名称(在本例中为ListViewItem)
      Y-用户执行的导致命令发生的操作(在本例中,双击)

    代码如下:

        public class ListViewItemDoubleClickCommandBehaviour : CommandBehaviorBase<ListViewItem>
        {
            public ListViewItemDoubleClickCommandBehaviour(ListViewItem controlToWhomWeBind)
            : base(controlToWhomWeBind)
            {
                controlToWhomWeBind.MouseDoubleClick += OnDoubleClick;
            }
    
            private void OnDoubleClick(object sender, System.Windows.RoutedEventArgs e)
            {
    
                ExecuteCommand();
    
            }
        }
    
    注: 我知道这看起来有很多复杂的代码,但是
        public ICommand DisplaySelectedItemCmd { get; protected set; }
    
        //This method goes in your constructor
        private void InitializeCommands()
        {
            //Initializes the command
            this.DisplaySelectedItemCmd = new RelayCommand(
                (param) =>
                {
                    this.DisplaySelectedItem((object)param);
                },
                (param) => { return this.CanDisplaySelectedItem; }
            );
        }      
        //The parameter should be your listview's selected item. I have no idea what type it is so I made it an object
        public void DisplaySelectedPolicy(object selectedListViewItem)
        {
            //Code to perform when item is double clicked
        }
    
        private bool CanDisplaySelectedPolicy
        {
            get
            {
                return true; //Change this bool if you have any reason to disable the double clicking, as this bool basically is linked to the double click command firing.
            }
        }
    
     xmlns:commands="clr-namespace:CommandHandling" 
    
     <Style TargetType="{x:Type ListViewItem}" x:Key="{x:Type ListViewItem}" >
           <Setter Property="commands:DoubleClick.Command" Value="{Binding Path=bleh}"/>
     </Style>
    
    <ListView IsSynchronizedWithCurrentItem="True" Name="listView" Margin="32,158,66,0" VerticalAlignment="Top">
            <ListView.ItemContainerStyle>                 
                 <Style TargetType="ListViewItem">
                    <EventSetter Event="PreviewMouseUp" Handler="itemClicked"></EventSetter>
                </Style>                 
            </ListView.ItemContainerStyle>            
            <ListView.View>
            ... etc
    
        EventSetter ev = new EventSetter();
        ev.Event = ListViewItem.PreviewMouseUpEvent;
        ev.Handler = new MouseButtonEventHandler(itemClicked);
    
        Style myStyle = new Style();
        myStyle.TargetType = typeof(ListViewItem);
    
        myStyle.Setters.Add(ev);
    
    
        listView.ItemContainerStyle = myStyle;
    
    void itemClicked(object sender, MouseButtonEventArgs e)
    {
         // item was licked in listview implement behavior in here
    }