1

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

I want to call the CheckItemCommand, which is already bound on the row checkbox, when i click anywhere on the row.

How can i specify the clicked row with

PreviewMouseLeftButtonDown="{Binding CheckItemCommand}"

?

G.Dealmeida
  • 325
  • 3
  • 14
  • what is 'MyTab'? could you provide a [MCVE]? – Mat Jan 25 '18 at 08:12
  • EDITED : I really thought it was clear enough (i already removed 90% of the code to be as easy to understand as possible). I also removed some converters, just in case this confuses you as well... – G.Dealmeida Jan 25 '18 at 08:42

3 Answers3

1

I found something that works. I'm not very found of this solution but it works fine, it's very simple to understand and can be done with very fiew code ( => KISS principle).

To have a proper "OnRowClick => DoStuff()" behavior I intercept all left click then, if the source is of the proper type, i call the Command_Execute() method.

Code :

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();
    }
}

I'm pretty sad there is no native way to do it via a mere Command pattern...

If someone has a better way to do it, feel free to had another, more elegant answer

G.Dealmeida
  • 325
  • 3
  • 14
1

You could use an interaction trigger:

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

The EventTrigger is defined in System.Windows.Interactivity.dll which is part of the Blend SDK: Visual Studio 2017 - What happened to Expression interactions?

Please refer to the following blog post for more information: https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/.

mm8
  • 163,881
  • 10
  • 57
  • 88
0

Instead of events I would use a mousebinding. Which you apply using a style:

When you click a row you're going to make it the selected item so you might be able to use that. Or maybe not, since I see you have some selecting going on there already.

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

The code you use for your command could use a property you bind to selecteditem. If that doesn't suit then you can use a commandparameter to provide the item clicked. I think that would look like:

CommandParameter="{Binding}"

That will give you the entire object that row has as it's datacontext - the item from Items. If your command is not in whatever object is presented to each item in the listview then there is a bit of a complication. You need to go find the datacontext of the listview ( as opposed to the row your mousebinding is going to end up "in" ). Do that using relativesource. That aspect will look something like:

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

Rather than just do this for you, I've tried to explain the principles involved. If you're new to commands and parameters then mvvmlight is very good and this article about relaycommand might clarify: https://msdn.microsoft.com/en-us/magazine/dn237302.aspx

Andy
  • 11,864
  • 2
  • 17
  • 20