The code bellow is includes extension from here (code normalized to fit StackOverflow screen witdh, sorry).
Imports System.ComponentModel
Imports System.Windows.Threading
Namespace Components
  Public NotInheritable Class DataGridSelectionChangingBehavior
    Public Shared Function GetEnableSelectionChanging(
      ByVal element As DataGrid) As Boolean
      If element Is Nothing Then Throw New ArgumentNullException("element")
      Return element.GetValue(EnableSelectionChangingProperty)
    End Function
    Public Shared Sub SetEnableSelectionChanging(
        ByVal element As DataGrid, ByVal value As Boolean)
      If element Is Nothing Then Throw New ArgumentNullException("element")
      element.SetValue(EnableSelectionChangingProperty, value)
    End Sub
    Public Shared ReadOnly EnableSelectionChangingProperty As _
         DependencyProperty =
      DependencyProperty.RegisterAttached("EnableSelectionChanging",
        GetType(Boolean),
        GetType(DataGridSelectionChangingBehavior),
        New FrameworkPropertyMetadata(False,
          New PropertyChangedCallback(
            AddressOf EnableSelectionChanging_PropertyChanged)))
    Public Shared Sub AddSelectionChangingHandler(
      ByVal element As DataGrid, handler As SelectionChangingEventHandler)
      If element IsNot Nothing Then _
        element.AddHandler(
          DataGridSelectionChangingBehavior.SelectionChangingEvent, handler)
    End Sub
    Public Shared Sub RemoveSelectionChangingHandler(
      ByVal element As DataGrid, handler As SelectionChangingEventHandler)
      If element IsNot Nothing Then _
        element.RemoveHandler(
          DataGridSelectionChangingBehavior.SelectionChangingEvent, handler)
    End Sub
    Public Shared ReadOnly SelectionChangingEvent As RoutedEvent =
      EventManager.RegisterRoutedEvent("SelectionChanging",
        RoutingStrategy.Bubble,
        GetType(SelectionChangingEventHandler),
        GetType(DataGridSelectionChangingBehavior))
    Private Shared Sub EnableSelectionChanging_PropertyChanged(
      ByVal sender As Object, ByVal e As DependencyPropertyChangedEventArgs)
      Dim dataGrid = DirectCast(sender, DataGrid)
      If CBool(e.NewValue) Then
        AddHandler dataGrid.PreparingCellForEdit,
          AddressOf DataGrid_PreparingCellForEdit
        AddHandler dataGrid.SelectionChanged,
          AddressOf DataGrid_SelectionChanged
      Else
        RemoveHandler dataGrid.PreparingCellForEdit,
          AddressOf DataGrid_PreparingCellForEdit
        RemoveHandler dataGrid.SelectionChanged,
          AddressOf DataGrid_SelectionChanged
        RecentColumn.Remove(dataGrid)
      End If
    End Sub
    Private Shared Sub DataGrid_SelectionChanged(
      ByVal sender As Object, ByVal e As SelectionChangedEventArgs)
      If e.RemovedItems.Count = 0 Then Exit Sub
      Dim dataGrid = DirectCast(sender, DataGrid)
      Dim removed = e.RemovedItems(0)
      Dim row = dataGrid.GetContainerFromItem(Of DataGridRow)(removed)
      Dim scea As New SelectionChangingEventArgs(row,
        DataGridSelectionChangingBehavior.SelectionChangingEvent, dataGrid)
      dataGrid.RaiseEvent(scea)
      If scea.Cancel Then
        RemoveHandler dataGrid.SelectionChanged,
          AddressOf DataGrid_SelectionChanged
        Dim operation = dataGrid.Dispatcher.BeginInvoke(
          Sub()
            dataGrid.SelectedItem = removed
            Dim column As DataGridColumn = Nothing
            If RecentColumn.TryGetValue(dataGrid, column) Then
              Dim cellsPanel =
                row.GetVisualDescendant(Of DataGridCellsPanel)().
                  Children.Cast(Of DataGridCell)()
              Dim recentCell =
                If(cellsPanel.SingleOrDefault(
                   Function(cell) cell.Column Is column),
                     cellsPanel.FirstOrDefault)
              If recentCell IsNot Nothing Then
                recentCell.IsEditing = True
                Keyboard.Focus(recentCell)
              End If
            End If
          End Sub,
          DispatcherPriority.ContextIdle)
        AddHandler operation.Completed,
          Sub(s, ea) AddHandler dataGrid.SelectionChanged,
            AddressOf DataGrid_SelectionChanged
      End If
    End Sub
    Private Shared m_RecentColumn As Dictionary(Of DataGrid, DataGridColumn)
    Public Shared ReadOnly Property RecentColumn() As Dictionary(Of DataGrid, 
                                                            DataGridColumn)
      Get
        If m_RecentColumn Is Nothing Then m_RecentColumn =
          New Dictionary(Of DataGrid, DataGridColumn)()
        Return m_RecentColumn
      End Get
    End Property
    Private Shared Sub DataGrid_PreparingCellForEdit(
      ByVal sender As Object, e As DataGridPreparingCellForEditEventArgs)
      Dim dataGrid = DirectCast(sender, DataGrid)
      RecentColumn(dataGrid) = e.Column
    End Sub
  End Class
  Public Delegate Sub SelectionChangingEventHandler(
    ByVal sender As Object, ByVal e As SelectionChangingEventArgs)
  Public Class SelectionChangingEventArgs : Inherits RoutedEventArgs
    Public Sub New(ByVal row As DataGridRow, routedEvent As RoutedEvent)
      MyBase.New(routedEvent)
      m_CurrentRow = row
    End Sub
    Public Sub New(ByVal row As DataGridRow,
                   ByVal routedEvent As RoutedEvent,
                   ByVal source As Object)
      MyBase.New(routedEvent, source)
      m_CurrentRow = row
    End Sub
    Private m_CurrentRow As DataGridRow
    Public ReadOnly Property CurrentRow() As DataGridRow
      Get
        Return m_CurrentRow
      End Get
    End Property
    Public ReadOnly Property Item() As Object
      Get
        If CurrentRow IsNot Nothing Then Return CurrentRow.Item
        Return Nothing
      End Get
    End Property
    Public Property Cancel As Boolean
  End Class
End Namespace
Usage:
<DataGrid Name="dg"
src:DataGridSelectionChangingBehavior.EnableSelectionChanging="True" 
src:DataGridSelectionChangingBehavior.SelectionChanging="dg_SelectionChanging">
Code behind (pseudu):
Private Sub dg_SelectionChanging(ByVal sender As Object, 
    ByVal e As SelectionChangingEventArgs)
  If e.CurrentRow.IsEditing Then
    Dim item = TryCast(e.CurrentRow.Item, MyEntityType)
    If item IsNot Nothing AndAlso item.IsValid Then
      Dim dataGrid = DirectCast(sender, DataGrid)
      Dim committed = dataGrid.CommitEdit(DataGridEditingUnit.Row, True)
      If committed Then Exit Sub
    End If
    e.Cancel = True
  End If
End Sub
Note: visual studio might not show the event in the intellisense and might even generate a design-time error, but it should compile and work perfect.
FYI: code formatted modified to fit SO screen.