Peter Szekeli
Peter Szekeli

Reputation: 2800

WPF DataGrid - bind dataitem's property as CommandParameter

I recently started to familiarize myself with WPF / MVVM, but I got stuck with bindings. I have an ObservableCollection of Customer objects, I bind this to a DataGrid. What I want to achieve is to bind the item's ID property as a parameter of a Button's command.

Here's the relevant code from the CustomerViewModel.cs file

private ObservableCollection<Customer> _customer = new ObservableCollection<Customer>();
public ObservableCollection<Customer> Customers
{
    get
    {
        return _customers;
    }
    set
    {
        SetProperty(ref _customers, value);
    }
}

private ICommand _openCustomerCommand;
public ICommand OpenCustomerCommand
{
    get
    {
        return _openCustomerCommand ?? (_openCustomerCommand = new RelayCommand(param => OpenCustomer((int)param)));
    }
}

and the XAML from CustomerView.xaml:

<DataGrid ItemsSource="{Binding Customers}" >
  <DataGridTemplateColumn Header="Open" Width="Auto">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Button Content="Open" 
                    Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.OpenCustomerViewCommand}"
                    CommandParameter="{Binding Customers/ID}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
  </DataGridTemplateColumn>
</DataGrid>

My problem is the following: according to http://www.wpftutorial.net/BindingExpressions.html I can use the forward slash (/) to access the current item of the collection. However, in that case, the received value is null.

I saw Bind CommandParameter to DataItem for a Button in a DataGrid, which suggests to use CommandParameter={Binding}, but then I receive the full object bound to the row, which is okay, but not really what I'm looking for.

Upvotes: 1

Views: 6877

Answers (2)

Peter Szekeli
Peter Szekeli

Reputation: 2800

Eventually I figured it out. Despite the mentioned issues, Nitin Joshi's suggestion compiles and works fine in runtime.

However, when I defined the underlying DataType of the collection in the DataTemplate tag, then I got the behavior I expected (e.g. having Intellisense support):

<Window x:Class="WPF_Demo.View.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:model="clr-namespace:WPF_Demo.Model"
        Title="MainWindow" Height="300" Width="300"
        DataContext="{StaticResource MainWindowViewModel}"
        >
    <Grid>
        <DataGrid ItemsSource="{Binding Customers}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding ID}"></DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding FullName}"></DataGridTextColumn>
                <DataGridTemplateColumn Header="Open" Width="Auto">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate DataType="model:Customer">
                            <Button Content="Open" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.OpenCustomerViewCommand}" CommandParameter="{Binding ID}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Upvotes: 2

Nitin Joshi
Nitin Joshi

Reputation: 1668

If you property name is ID then just use following

<DataGrid ItemsSource="{Binding Customers}" >
  <DataGridTemplateColumn Header="Open" Width="Auto">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Button Content="Open" 
                    Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.OpenCustomerViewCommand}"
                    CommandParameter="{Binding ID}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
  </DataGridTemplateColumn>
</DataGrid>

Upvotes: 4

Related Questions