4

Within my WPF - MVVM application, I have a ListView in which there's a GridView. On Double clicking a row in the GridView, I want to read the text in a column in that row.

I want to use commands to maintain the MVVM pattern.

I know that one can use InputBindings to wire up a command for DoubleClick event. but there's no InputBindings for GridView.

Any idea how to achieve the functionality??

Thanks


Note - Want to know whether the above can be achieved by purely using commands - without code-behind for DoubleClick event handling?

KhannaB7
  • 265
  • 5
  • 17
  • It would help if you included some of the XAML code you've written. – Sridhar Jan 30 '15 at 09:54
  • Could it be that you want to achieve the same thing as [here](http://stackoverflow.com/questions/728205/wpf-listview-attaching-a-double-click-on-an-item-event)? – Claudio P Jan 30 '15 at 09:59
  • @Claudio - the Link you mentioned specifies using an event - but that would use Code-Behind. In MVVM that would not be very much accepted. I want to know whether is it possible to achieve the desired functionality using pure Commands? – KhannaB7 Jan 30 '15 at 10:09
  • Whit the help of Interaction-Triggers you can simply bind an event to a command in your Viewmodel – Claudio P Jan 30 '15 at 10:11
  • https://zamjad.wordpress.com/2014/11/19/convert-event-to-command-using-blend-sdk/ here is an example – blindmeis Jan 30 '15 at 13:23
  • ClaudioP & blindmeis - your suggestions on using interactivity dll 's features seems good but i found out a solution without interactivity dll. Thanks for your suggestions. – KhannaB7 Feb 02 '15 at 05:23

3 Answers3

4

I used a CellTemplate for a column within my GridView, in that celltemplate I provided InputBindings - MouseBinding for Double Click event. This turns the double click event into a command & then i send the Cell's text as a command parameter.

<ListView x:Name="listview1" ItemsSource="{Binding DataCollection}"  >

    <ListView.View>
        <GridView ColumnHeaderContainerStyle="{StaticResource ColumnHeaderStyle}">

            <GridViewColumn Header="ID"  Width="auto" DisplayMemberBinding="{Binding ID}" />
            <GridViewColumn Header="PrimaryFile"   Width="auto"  >
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding PrimaryFile}">
                            <TextBlock.InputBindings>
                                <MouseBinding Gesture="LeftDoubleClick" Command="{Binding Path=DataContext.ShowFileCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" CommandParameter="{Binding PrimaryFile}"/>
                            </TextBlock.InputBindings>
                        </TextBlock>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>

</ListView>

Here, the usercontrol's datacontext was set to a viewmodel, and the ShowFileCommand was exposed on my viewmodel.

So on double clicking Cells in 2nd column, command was raised along with the text in the cell as command parameter

KhannaB7
  • 265
  • 5
  • 17
  • 1
    Thanks i got this to work. and is a good direction on what i required. however i cannot get this to work on multiple columns unless i replicate the same code for each column. – New Bee Jul 27 '15 at 00:08
  • This problem was driving me crazy too, the only disadvantage about this solution is that I have to set the InputBindings for every GridViewColumn – luis_laurent Nov 28 '19 at 04:33
2

To get KhannaB7's suggestion to work on all columns within you grid view you will need to do this

Set a DataTemplate in your resources

  <UserControl.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="GridViewCellTemplateStyle">
                <TextBlock Text="{Binding}">
                    <TextBlock.InputBindings>
                        <MouseBinding Gesture="LeftDoubleClick" Command="{Binding DataContext.CommandDoubleClick, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}"/>
                    </TextBlock.InputBindings>
                </TextBlock>
            </DataTemplate>
        </ResourceDictionary>
    </UserControl.Resources>

Create your grid view and make the columns inherit this datatemplate

 <ListView>
            <ListView.View>
                <GridView>
                    <GridViewColumn Width="Auto" Header="Column1" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
                    <GridViewColumn Width="Auto" Header="Column2" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
                    <GridViewColumn Width="Auto" Header="Column3" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
                    <GridViewColumn Width="Auto" Header="Column4" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
                </GridView>
            </ListView.View>
        </ListView>

Of course you can put what ever you want in your template. mine just shows how to make a double click for a grid view column row

New Bee
  • 991
  • 1
  • 13
  • 24
1

I was trying to find a good solution and tried this one out but sadly it did not work. For anyone in the same boat and happening to find themselves here, I found two really solid approaches. There are many OTHER approaches to this problem, however I wanted to avoid use of any additional DLLs (aka use of interactivity) or other frameworks.

Attached Behavior

A user by the handle dlf posted an excellent answer here: GridView DoubleClick He posted an awesome attached behavior and I have tested it under multiple conditions and it works very well.

Pure XAML

I personally try to do as much as I can in XAML. Essentially I create a ControlTemplate for the ListViewItem. The ControlTemplate needs to be tweaked to both contain whatever highlight color effect you want and must also contain the data for whatever ever row you are selecting. The great part about this is works well even with multiple columns. You will also need a separate ControlTemplate for each Command.

Here is an example with a 2 column ListView and a gradient highlight effect that bound to collection. One thing to make note of in my ControlTemplate, I set the TextBlock width to match the width of the column.

Hope this helps anyone looking.

Control Template:

    <ControlTemplate x:Key="Selected_Item_Template" TargetType="{x:Type ListViewItem}">
        <Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="19" Margin="0,0,0,0" BorderBrush="LightGray" BorderThickness="1">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF74A1C7" Offset="0.5"/>
                    <GradientStop Color="SteelBlue" Offset="0.5"/>
                </LinearGradientBrush>
            </Border.Background>
            <Border.InputBindings>
                <MouseBinding Gesture="LeftDoubleClick" 
                              CommandParameter="{Binding SelectedItems, ElementName=your_listview}"
                              Command="{Binding Path=DataContext.Some_DoubleClick_ICommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/>
            </Border.InputBindings>
            <DockPanel>
                <TextBlock Width="{Binding ActualWidth, ElementName=column_1}" Margin="6,0,0,0" Text="{Binding Column1}" />
                <TextBlock Margin="0,0,0,0" Text="{Binding Column2}" />
            </DockPanel>
        </Border>
    </ControlTemplate>

The ListView:

    <ListView x:Name="your_listview"
              ItemsSource="{Binding Some_Source_Collection}"
              SelectedIndex="{Binding Some_Int_Variable}">

        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Setter Property="BorderBrush" Value="LightGray" />
                <Setter Property="BorderThickness" Value="0,0,0,1" />

                <Style.Triggers>

                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true" />
                            <Condition Property="Selector.IsSelectionActive" Value="true" />
                        </MultiTrigger.Conditions>
                        <Setter Property="Foreground" Value="White" />
                        <Setter Property="Template" Value="{StaticResource Selected_Item_Template}" />
                    </MultiTrigger>

                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true" />
                            <Condition Property="Selector.IsSelectionActive" Value="false" />
                        </MultiTrigger.Conditions>
                        <Setter Property="Foreground" Value="White" />
                        <Setter Property="Template" Value="{StaticResource Selected_Item_Template}" />
                    </MultiTrigger>

                </Style.Triggers>

            </Style>
        </ListView.ItemContainerStyle>

        <ListView.View>
            <GridView x:Name="your_listview_gridview">
                <GridViewColumn x:Name="column_1" Header="Name:" Width="100"
                                DisplayMemberBinding="{Binding Column1}">

                    <GridViewColumn.HeaderContainerStyle>

                        <Style TargetType="{x:Type GridViewColumnHeader}">
                            <Setter Property="HorizontalContentAlignment" Value="Left" />
                            <Setter Property="VerticalContentAlignment" Value="Center" />
                            <Setter Property="IsEnabled" Value="True"/>
                        </Style>

                    </GridViewColumn.HeaderContainerStyle>

                </GridViewColumn>

                <GridViewColumn x:Name="column_2" Header="Path:" Width="250"
                                DisplayMemberBinding="{Binding Column2}">

                    <GridViewColumn.HeaderContainerStyle>

                        <Style TargetType="{x:Type GridViewColumnHeader}">
                            <Setter Property="HorizontalContentAlignment" Value="Left" />
                            <Setter Property="VerticalContentAlignment" Value="Center" />
                            <Setter Property="IsEnabled" Value="True"/>
                        </Style>

                    </GridViewColumn.HeaderContainerStyle>

                </GridViewColumn>
            </GridView>
        </ListView.View>

    </ListView>

PM me if you have questions about or if you need help casting SelectedItems into something usable.

David Bentley
  • 824
  • 1
  • 8
  • 27