Let us say that the DataGriddisplays employees information, for each employee we store his Id, Name and Address. Lets add an additional Boolean property for each employee property (e.g. Id and IsIdSelected, Name and IsNameSelected) this Boolean property will be bound to the DataGrid.IsSelected property, thus, it represents whether the cell is selected or not, you could also use it to select the cell displaying the designated property programatically by setting it to True. See the following code:
/// <summary>
/// A class that represents an employee. Notice that with each property
/// (e.g. Id) there is a Boolean property that has a similar name (e.g. IsIdSelected)
/// this Boolean property will be bound to the relevant DataGridCell.IsSelected
/// property to indicate whether the cell representing this property were selected
/// or not. In other words if you want to know the selected properties at any moment
/// you just need to iterate through the employees collection, and examine each
/// Boolean property for each property :D
/// </summary>
public class Employee
{
public int? Id { get; set; }
public bool IsIdSelected { get; set; }
public string Name { get; set; }
public bool IsNameSelected { get; set; }
public string Address { get; set; }
public bool IsAddressSelected { get; set; }
}
The code behind:
using System.Collections.ObjectModel;
using System.Windows;
namespace CellSelection
{
public partial class MainWindow : Window
{
/// <summary>
/// The DataGrid will be bound to this collection
/// </summary>
private ObservableCollection<Employee> _collection;
public MainWindow()
{
InitializeComponent();
// Initialize the employees collection with some test data
_collection =
new ObservableCollection<Employee>
{
new Employee {Id = 1, Name = "Mohammed A. Fadil", Address = "..."},
new Employee {Id = 485, Name = "Khalid Zein", Address = "..."},
new Employee {Id = 64, Name = "Ahmed Mubarak", Address = "..."},
new Employee {Id = 364, Name = "Ali Ebraheim", Address = "..."},
};
DataContext = _collection;
}
private void OnExportButtonClick(object sender, RoutedEventArgs e)
{
// Now, concatinate all the selected cells
var str = string.Empty;
foreach (var emp in _collection)
{
if (emp.IsIdSelected)
str += string.Format("{0}, ", emp.Id);
if (emp.IsNameSelected)
str += string.Format("{0}, ", emp.Name);
if (emp.IsAddressSelected)
str += string.Format("{0}", emp.Address);
str += "\n";
}
// Instead of displaying this message you could export these cells to Excel
// in the format you need.
MessageBox.Show(str);
}
}
}
The XAML code:
<Window x:Class="CellSelection.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="275*" />
<RowDefinition Height="36*" />
</Grid.RowDefinitions>
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False"
SelectionMode="Extended" SelectionUnit="CellOrRowHeader">
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Binding="{Binding Id}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="IsSelected">
<Setter.Value>
<Binding Path="IsIdSelected" Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged"/>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Name" Binding="{Binding Name}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="IsSelected">
<Setter.Value>
<Binding Path="IsNameSelected" Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged"/>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Address" Binding="{Binding Address}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="IsSelected">
<Setter.Value>
<Binding Path="IsAddressSelected" Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged"/>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<Button Content="Export Selection" Grid.Row="1" HorizontalAlignment="Right"
Click="OnExportButtonClick" Margin="5"/>
</Grid>
</Window>
Note that for each DataGrid column you have to add a CellStyle that binds each column designated Boolean property to it's DataGridCell.IsSelected property, set this binding mode to Mode="TwoWay" in-order to support selecting cells programatically (In this case you have to implement INotifyPropertyChanged on the Employee class).
With this solution you neither need the helper function nor to access the DataGrid actual cells any more, just iterate through your collection, determine the selected properties and process them as needed.