首页 > 解决方案 > WPF 绑定 ListView 双击事件

问题描述

我是 WPF 的新手,所以请原谅以下任何没有意义的内容......

我已经设置了一个视图模型,它绑定到一个 WPF 列表视图数据模板。源对象(属于一个名为 BrowserItem 的类)位于 ObservableCollection 中,我使用 CollectionViewSource 将它们显示在 ListView 中 - 经过几次头痛之后,这确实很好。

我认为最简单的部分是用户双击某物时的处理,但我错了。

附加到 ListView 的事件返回 TextBlock 控件而不是单击的 BrowserItem 源对象。

任何人都可以指出一种在单击控件时获取原始项目(BrowserItem)的简单方法 - 我已经看到了几种方法,但在我简单的头脑中它们似乎都非常复杂。

一个简单的例子会很棒。

这是列表视图的 XAML(如果使用):

           <ListView Name="ViewList"
                  ItemsSource="{Binding GroupItems}">
            <ListView.ItemTemplate>
                <DataTemplate>

                    <StackPanel Orientation="Horizontal">
                        <Expander>
                            <Expander.Style>
                                <Style>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=Children.Count}"
                                                     Value="0">
                                            <Setter Property="Expander.Visibility"
                                                    Value="Collapsed" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Expander.Style>
                            <ListBox ItemsSource="{Binding Children}" />
                        </Expander>
                        
                        <TextBlock Text="{Binding Name}">

                            <TextBlock.Style>

                                <Style TargetType="{x:Type TextBlock}">
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Active}"
                                                     Value="true">
                                            <Setter Property="Background"
                                                    Value="YellowGreen" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>

                            </TextBlock.Style>
                        </TextBlock>
                    </StackPanel>

                 </DataTemplate>
            </ListView.ItemTemplate>

            <ListView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate>
                                        <Expander>
                                            <Expander.Header>
                                                <TextBlock Text="{Binding Name}" />
                                            </Expander.Header>
                                            <ItemsPresenter />
                                        </Expander>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ListView.GroupStyle>

        </ListView>

谢谢。

标签: wpflistviewevents

解决方案


您可以使用 EventSetter 将 MouseDoubleClick 事件添加到列表视图,如下所示:

<ListView ItemsSource="{Binding Source}" SelectedItem="{Binding SelectedModel, Mode=TwoWay}">
        <!--<Behaviors:Interaction.Triggers>
            <Behaviors:EventTrigger EventName="MouseDoubleClick">
                <Behaviors:InvokeCommandAction Command="{Binding DataContext.Command, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" />
            </Behaviors:EventTrigger>
        </Behaviors:Interaction.Triggers>-->
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <EventSetter Event="MouseDoubleClick" Handler="ListViewItem_MouseDoubleClick" />
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate DataType="{x:Type local:Model}">
                <TextBlock Text="{Binding Age}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

这样,您只需在代码中处理它,而不是在 ViewModel 中。

如果你想在视图模型中处理它,你需要一个这样的类:

public class EventToCommand
{
    public static string GetEventName(DependencyObject obj)
    {
        return (string)obj.GetValue(EventNameProperty);
    }

    public static void SetEventName(DependencyObject obj, string value)
    {
        obj.SetValue(EventNameProperty, value);
    }

    public static readonly DependencyProperty EventNameProperty =
        DependencyProperty.RegisterAttached("EventName", typeof(string), typeof(EventToCommand), new PropertyMetadata("", OnEventNameChanged));

    public static void OnEventNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
       
    }

    public static ICommand GetCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(CommandProperty);
    }

    public static void SetCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(CommandProperty, value);
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(EventToCommand), new PropertyMetadata(OnCommandChanged));


    public static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var element = d as FrameworkElement;
        EventInfo eventInfo =  d.GetType().GetEvent(GetEventName(d));
        var eventHandlerMethodInfo = typeof(EventToCommand).GetMethod("Invoke", BindingFlags.Static | BindingFlags.Public);
        eventInfo.AddEventHandler(d, Delegate.CreateDelegate(eventInfo.EventHandlerType, eventHandlerMethodInfo));
        
    }
    public static void Invoke(object sender,EventArgs e)
    {
        var command = GetCommand(sender as FrameworkElement);
        command.Execute(e);
    }

}

并像这样使用 EventToCommand 类:

 <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="local:EventToCommand.EventName" Value="MouseDoubleClick" />
                <Setter Property="local:EventToCommand.Command" Value="{Binding DataContext.Command, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" />
            </Style>
        </ListView.ItemContainerStyle>

推荐阅读