Reputation: 2800
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
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
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