I would create my data object behind myDataGrid
with the following properties
ObservableCollection<MyObject> Records
List<int> Ids
List<string> FirstNames
List<string> LastNames
Then bind my DataGrid using TemplateColumns that have ComboBoxes which bind to the collections of values in the DataContext, like this:
<DataGrid ItemsSource="{Binding Records}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.Ids}"
SelectedItem="{Binding Id}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.FirstNames}"
SelectedItem="{Binding FirstName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.LastNames}"
SelectedItem="{Binding LastName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
And I'd populate my lists at the time the grid loads (and maybe update it as items change if needed)
Ids = Records.Select(p => p.Id).ToList();
FirstNames = Records.Select(p => p.FirstName).ToList();
LastNames = Records.Select(p => p.LastName).ToList();