The Resharper/Intellisense inference is incorrect inside of DataGridTemplate
.
This can cause confusion, In order to correct that, the DataTemplate should have an explicit DataType referencing the type that the row is being bound to.
There are 2 ways I found of solving your question, Using a Relative Binding for the Command , so that it binds using the Context of the DataGrid, not the current row, Or creating an x:Name attribute on an element that has the context you wish to bind to.
It's my belief that the relative binding is cleaner if you are trying to access an ancestor, but if you need to bind to something elsewhere in the tree, then maybe ElementName will allow that.
XAML:
<Window x:Class="TestBindings.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestBindings"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:WindowViewModel/>
</Window.DataContext>
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<GroupBox x:Name="Test" Header="Grid" Grid.Column="0"> <!-- #2 Add a name to the element you need to bind to. -->
<DataGrid ItemsSource="{Binding RowList}" IsSynchronizedWithCurrentItem="True" SelectionUnit="FullRow" >
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="local:RowViewModel"><!-- Needed for correct inference in XAML editor -->
<!-- #1 Cleaner solution as it doesn't depend on names -->
<Button Content="{Binding Path=RowCount}" Command="{Binding Path=DataContext.NineCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" CommandParameter="{Binding}" />
<!-- #2 Naming the element explicitly probably allows you to jump elsewhere in the tree -->
<Button Content="{Binding Path=RowCount}" Command="{Binding Path=DataContext.NineCommand, ElementName=Test}" CommandParameter="{Binding}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</GroupBox>
<GroupBox Header="{Binding Path=SelectedRow.RowCount}" Grid.Column="1">
<Label Content="{Binding Path=RowList/RowCount}"></Label>
</GroupBox>
</Grid>
</Window>
Class:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Data;
using System.Windows.Input;
using Microsoft.Expression.Interactivity.Core;
using Microsoft.Practices.Prism.ViewModel;
namespace TestBindings
{
public class RowViewModel : NotificationObject
{
private static int _max = 0;
private int _rowCount;
public int RowCount
{
get { return _rowCount; }
set
{
if (_rowCount == value) return;
_rowCount = value;
RaisePropertyChanged(nameof(RowCount));
}
}
public RowViewModel()
{
_rowCount = _max++;
}
}
public class TypedCommand<T> : ICommand
{
private readonly Predicate<T> _canExecute;
private readonly Action<T> _execute;
public TypedCommand(Action<T> execute, Predicate<T> canExecute = null)
{
this._canExecute = canExecute;
this._execute = execute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute((T) parameter);
}
public void Execute(object parameter)
{
_execute?.Invoke((T) parameter);
}
public event EventHandler CanExecuteChanged;
}
public class WindowViewModel : NotificationObject
{
public ObservableCollection<RowViewModel> RowList { get; } = new ObservableCollection<RowViewModel>();
private RowViewModel _selectedRow;
public RowViewModel SelectedRow
{
get { return _selectedRow; }
private set
{
if (_selectedRow == value) return;
_selectedRow = value;
RaisePropertyChanged(nameof(SelectedRow));
}
}
private static readonly Action<RowViewModel> DeleteAction = new Action<RowViewModel>(row => row.RowCount=99);
public ICommand NineCommand { get; } = new TypedCommand<RowViewModel>(DeleteAction);
public WindowViewModel()
{
//0
RowList.Add(new RowViewModel());
//1
RowList.Add(new RowViewModel());
//2
RowList.Add(new RowViewModel());
}
}
}