Hi, you can include DataGridTemplateColumn with Button. Command is bound to ICommand property of ViewModel and CommandParameter is bound to data item of row. Clicking button the event method gets the reference to data object of clicked row.
<Page
x:Class="App1.Page05"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App05"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<local:ViewModel x:Key="vm"/>
</Page.Resources>
<Grid DataContext="{StaticResource vm}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<controls:DataGrid Grid.Row="0" ItemsSource="{Binding View}" Height="200">
<controls:DataGrid.Columns>
<controls:DataGridTemplateColumn>
<controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<Button Content="Select" Command="{Binding Cmd, Source={StaticResource vm}}" CommandParameter="{Binding}"/>
</StackPanel>
</DataTemplate>
</controls:DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumn>
</controls:DataGrid.Columns>
</controls:DataGrid>
<TextBlock Grid.Row="1" Text="{Binding Log}"/>
</Grid>
</Page>
--------------------------------------------------------------
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
namespace App05
{
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<Data> col;
public ObservableCollection<Data> View
{
get
{
if (col == null) LoadData();
return col;
}
}
public string Log { get; set; }
public ICommand Cmd { get => new RelayCommand(CmdExec); }
private void CmdExec(Object obj)
{
var d = obj as Data; // get data object from CommandParameter
if (d == null) return; // exit if there's no data
Log = $"Row ID: {d.ID}, Info: {d.Info}"; // write info
OnPropertyChanged(nameof(Log)); // refresh UI
}
private void LoadData()
{
col = new ObservableCollection<Data>();
for (int i = 1; i < 100; i++) col.Add(new Data() { ID = i, Info = $"Row {i}" });
}
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged([CallerMemberName] string propName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
#endregion
}
public class Data
{
public int ID { get; set; }
public string Info { get; set; }
}
public class RelayCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute) { _execute = execute; _canExecute = canExecute; }
public bool CanExecute(object parameter) => (_canExecute == null) ? true : _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}