C#WPF:将listview左键单击绑定到数据项命令

时间:2018-01-25 07:55:10

标签: c# wpf mvvm

考虑这个xaml:

<ListView ItemsSource="{Binding Items}" PreviewMouseLeftButtonDown="{Binding CheckItemCommand}">
    <ListView.View>
        <GridView>
            <GridViewColumn>
                <GridViewColumn.Header>
                    <CheckBox IsThreeState="True" 
                              IsChecked="{Binding IsSelectAll, Mode=TwoWay}"
                              Command="{Binding CheckAllCommand}">
                    </CheckBox>
                </GridViewColumn.Header>
                <GridViewColumn.CellTemplate>
                    <DataTemplate DataType="x:MyObject">
                        <Grid>
                            <TextBlock Text="{Binding LoadingState}"/>
                            <CheckBox IsThreeState="False" 
                                      IsChecked="{Binding IsSelected, Mode=TwoWay}"
                                      Command="{Binding CheckItemCommand}">
                            </CheckBox>
                        </Grid>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="{Binding MyObject.Header_Name}"  
                            DisplayMemberBinding="{Binding Name}" />
            <GridViewColumn Header="{Binding MyObject.Header_CreationDate}" 
                            DisplayMemberBinding="{Binding CreationDate}" />
            <GridViewColumn Header="{Binding MyObject.Header_NumberOfStuff1}"
                            DisplayMemberBinding="{Binding stuff1}"/>
            <GridViewColumn Header="{Binding MyObject.Header_NumberOfStuff2}" 
                            DisplayMemberBinding="{Binding stuff2}"/>
        </GridView>
    </ListView.View>
</ListView>

当我点击行上的任何地方时,我想调用CheckItemCommand,它已经绑定在行复选框上。

如何使用

指定单击的行
PreviewMouseLeftButtonDown="{Binding CheckItemCommand}"

3 个答案:

答案 0 :(得分:1)

您可以使用互动触发器:

<ListView ItemsSource="{Binding Items}"
          xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="PreviewMouseLeftButtonDown" >
            <i:InvokeCommandAction Command="{Binding CheckItemCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    ...
</ListView>

EventTriggerSystem.Windows.Interactivity.dll中定义,它是Blend SDK的一部分:Visual Studio 2017 - What happened to Expression interactions?

有关详细信息,请参阅以下博客文章:https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/

答案 1 :(得分:0)

我会使用鼠标绑定而不是事件。 您使用样式申请:

当您单击某行时,您将使其成为所选项目,以便您可以使用该项目。或许不是,因为我看到你已经有一些选择了。

    <Style TargetType="ListViewItem">
  <Setter Property="local:AddToInputBinding.Binding">
    <Setter.Value>
      <MouseBinding Gesture="LeftClick" Command="{Binding YourCommand}" />    
    </Setter.Value>
  </Setter>

您用于命令的代码可以使用绑定到selecteditem的属性。 如果这不适合,那么您可以使用命令参数来提供单击的项目。 我认为这看起来像:

CommandParameter="{Binding}"

这将为您提供行所拥有的整个对象,因为它是datacontext - 来自Items的项目。 如果你的命令不在列表视图中的每个项目的任何对象中,那么就会出现一些复杂问题。 你需要找到listview的datacontext(而不是你的鼠标绑定将在“in”中结束的行)。 使用relativesource做那件事。 这方面看起来像:

Command="{Binding DataContext.YourCommand, 
                  RelativeSource={RelativeSource  
                                  AncestorType={x:Type ListView}}}"

我试图解释所涉及的原则,而不仅仅是为你做这件事。 如果你是命令和参数的新手,那么mvvmlight非常好,这篇关于relaycommand的文章可能会澄清: Guid.NewGuid().ToString()

答案 2 :(得分:0)

我找到了有用的东西。我不太了解这个解决方案,但它工作正常,理解非常简单,并且可以用非常好的代码完成(=&gt; KISS原则)。

要有一个正确的“OnRowClick =&gt; DoStuff()”行为,我拦截所有左键单击,如果源是正确的类型,我调用Command_Execute()方法。

代码:

public MyContainer()
{
    InitializeComponent();
    this.PreviewMouseDown += MyContainer_PreviewMouseDown;
}

private void MyContainer_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    var source = e.OriginalSource as FrameworkElement;
    var dataContext = source?.DataContext;
    if(dataContext.GetType() == typeof(ProperViewModel))
    {
        ((ProperViewModel)dataContext).Command_Execute();
    }
}

我很难过没有原生的方式通过纯粹的Command模式来做到这一点......

如果某人有更好的方法可以做到这一点,请随意提出另一个更优雅的答案