Search code examples
wpflistviewdata-bindinglistviewitemgridviewcolumn

Passing in as command parameter the value of a WPF ListView GridViewColumn


In an WPF ListView I have ListViewItems that consist of three columns, first column is an auto-increment column, second one is a TextBox and the last one contains two buttons (Edit and Delete) in the same column.

My ListView now looks as below:

<ListView x:Name="MyListView"
          AlternationCount="{Binding pathList.Count}"
          ItemsSource="{Binding pathList}" 
          IsSynchronizedWithCurrentItem="True">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="#" x:Name="LvItemId"
                            DisplayMemberBinding="{Binding (ItemsControl.AlternationIndex),
                            RelativeSource={RelativeSource AncestorType=ListViewItem}}"/>
            <GridViewColumn Header="Command sentence" Width="350" CellTemplate="{StaticResource NameColumnTemplate}"/>
            <GridViewColumn Width="70" Header="Edit / Delete" CellTemplate="{StaticResource AddDelItemTemplate}"/>
        </GridView>
    </ListView.View>
</ListView>

Below the CellTemplates:

<DataTemplate x:Key="FirstRowTemplate1">
    <Grid Width="190">
        <Button Content="Add" Command="{Binding Path=DataContext.AddCommand, ElementName=MyListView}" 
                Width="180" 
                HorizontalAlignment="Center"/>
    </Grid>
</DataTemplate>
<DataTemplate x:Key="NextRowTemplate1">
    <TextBox Text="{Binding PathString}"/>
</DataTemplate>
<DataTemplate x:Key="NameColumnTemplate">
    <ContentPresenter x:Name="ButtonPresenter"
                      Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"
                      ContentTemplate="{StaticResource NextRowTemplate1}"/>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Add}" Value="True">
            <Setter TargetName="ButtonPresenter"  
                    Property="ContentTemplate" 
                    Value="{StaticResource FirstRowTemplate1}"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Add}" Value="False">
            <Setter TargetName="ButtonPresenter"
                    Property="ContentTemplate"
                    Value="{StaticResource NextRowTemplate1}"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>
<DataTemplate x:Key="FirstRowTemplate2"/>
<DataTemplate x:Key="NextRowTemplate2">
    <StackPanel Orientation="Horizontal">
        <Button Content="Edit" Command="{Binding Path=DataContext.EditCommand, ElementName=MyListView}" CommandParameter="{Binding ElementName=LvItemId, Path=WhatToPutHere}"/>
        <Button Content="Delete" Command="{Binding Path=DataContext.DelCommand, ElementName=MyListView}" CommandParameter="{Binding ElementName=LvItemId, Path=WhatToPutHere}"/>
    </StackPanel>
</DataTemplate>
<DataTemplate x:Key="AddDelItemTemplate">
    <ContentPresenter x:Name="ButtonPresenter"
            Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"  
            ContentTemplate="{StaticResource NextRowTemplate2}"/>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Add}" Value="True">
            <Setter TargetName="ButtonPresenter"
                    Property="ContentTemplate" 
                    Value="{StaticResource FirstRowTemplate2}"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Add}" Value="False">
            <Setter TargetName="ButtonPresenter"
                    Property="ContentTemplate"
                    Value="{StaticResource NextRowTemplate2}"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

When Edit or Delete button are clicked I want to pass in as a command parameter the value that first GridViewColumn has for that ListViewItem. How can I do this?

For example:

<Button Content="Edit" Command="{Binding Path=DataContext.EditCommand, ElementName=MyListView}" CommandParameter="{Binding ElementName=LvItemId, Path=WhatToPutHere}"/>
<Button Content="Delete" Command="{Binding Path=DataContext.DelCommand, ElementName=MyListView}" CommandParameter="{Binding ElementName=LvItemId, Path=WhatToPutHere}"/>

Solution

  • The GridViewColumn defines the column itself, how it is populated, e.g. template, binding or width, but it does not have a reference to any of the items generated by the item container generator.

    In case of the first column you can copy the binding for the attached property AlternationIndex:

    <Button Content="Edit" Command="{Binding (ItemsControl.AlternationIndex), RelativeSource={RelativeSource AncestorType=ListViewItem}}"/>
    <Button Content="Delete" Command="{Binding (ItemsControl.AlternationIndex), RelativeSource={RelativeSource AncestorType=ListViewItem}}"/>