diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Data/DataGridDataItem.cs b/Microsoft.Toolkit.Uwp.SampleApp/Data/DataGridDataItem.cs
index f3d0bae93f2..c4b95f29e6a 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Data/DataGridDataItem.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Data/DataGridDataItem.cs
@@ -152,6 +152,8 @@ public string Parent_mountain
// You need to use DateTimeOffset to get proper binding to the CalendarDatePicker control, DateTime won't work.
public DateTimeOffset First_ascent { get; set; }
+ public bool IsFavorite { get; set; }
+
public string Ascents { get; set; }
bool INotifyDataErrorInfo.HasErrors
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DataGrid/DataGridCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DataGrid/DataGridCode.bind
index 874762b3798..a0755a1225f 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DataGrid/DataGridCode.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DataGrid/DataGridCode.bind
@@ -85,6 +85,7 @@
+
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.DataGrid/DataGrid/DataGrid.cs b/Microsoft.Toolkit.Uwp.UI.Controls.DataGrid/DataGrid/DataGrid.cs
index fcff002c18c..d6cba4d8cc8 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.DataGrid/DataGrid/DataGrid.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.DataGrid/DataGrid/DataGrid.cs
@@ -5727,16 +5727,39 @@ private void DataGrid_LostFocus(object sender, RoutedEventArgs e)
_focusedObject = null;
if (this.ContainsFocus)
{
- bool focusLeftDataGrid = true;
- bool dataGridWillReceiveRoutedEvent = true;
- DataGridColumn editingColumn = null;
-
- // Walk up the visual tree of the newly focused element
- // to determine if focus is still within DataGrid.
object focusedObject = GetFocusedElement();
DependencyObject focusedDependencyObject = focusedObject as DependencyObject;
- while (focusedDependencyObject != null)
+ // Interacting with a Popup should never cause
+ // DataGrid to commit row/cell edits
+ bool focusLeftDataGrid = focusedDependencyObject is not Popup;
+ bool editingElementFocused = false;
+
+ if (this.EditingRow != null && this.EditingColumnIndex != -1)
+ {
+ var editingColumn = this.ColumnsItemsInternal[this.EditingColumnIndex];
+ var editingElement = editingColumn.GetCellContent(this.EditingRow);
+
+ // Handle weird scenario for ComboBox and other ItemsControls
+ // that don't work with DependencyObject.ContainsChild( )
+ if (editingElement is not ItemsControl ic)
+ {
+ editingElementFocused = editingElement.ContainsChild(focusedDependencyObject);
+ }
+ else
+ {
+ editingElementFocused = ic.ItemsPanelRoot.ContainsChild(focusedDependencyObject);
+ }
+
+ if (editingElement == focusedDependencyObject)
+ {
+ focusLeftDataGrid = false;
+ }
+ }
+
+ // Walk up the visual tree of the newly focused element
+ // to determine if focus is still within DataGrid.
+ while (focusedDependencyObject != null && focusedDependencyObject is not Popup && focusLeftDataGrid && !editingElementFocused)
{
if (focusedDependencyObject == this)
{
@@ -5744,11 +5767,11 @@ private void DataGrid_LostFocus(object sender, RoutedEventArgs e)
break;
}
- // Walk up the visual tree. Try using the framework element's
- // parent. We do this because Popups behave differently with respect to the visual tree,
- // and it could have a parent even if the VisualTreeHelper doesn't find it.
- DependencyObject parent = null;
FrameworkElement element = focusedDependencyObject as FrameworkElement;
+
+ // Walk up the visual tree. Try using the framework element's
+ // parent.
+ DependencyObject parent;
if (element == null)
{
parent = VisualTreeHelper.GetParent(focusedDependencyObject);
@@ -5760,32 +5783,19 @@ private void DataGrid_LostFocus(object sender, RoutedEventArgs e)
{
parent = VisualTreeHelper.GetParent(focusedDependencyObject);
}
- else
- {
- dataGridWillReceiveRoutedEvent = false;
- }
}
focusedDependencyObject = parent;
}
- if (this.EditingRow != null && this.EditingColumnIndex != -1)
+ if (editingElementFocused)
{
- editingColumn = this.ColumnsItemsInternal[this.EditingColumnIndex];
-
- if (focusLeftDataGrid && editingColumn is DataGridTemplateColumn)
- {
- dataGridWillReceiveRoutedEvent = false;
- }
+ HandleLostFocusForExternalElement(focusedObject);
}
-
- if (focusLeftDataGrid && !(editingColumn is DataGridTemplateColumn))
+ else if (focusLeftDataGrid)
{
this.ContainsFocus = false;
- if (this.EditingRow != null)
- {
- CommitEdit(DataGridEditingUnit.Row, true /*exitEditingMode*/);
- }
+ CommitEdit(DataGridEditingUnit.Row, true /*exitEditingMode*/);
ResetFocusedRow();
ApplyDisplayedRowsState(this.DisplayData.FirstScrollingSlot, this.DisplayData.LastScrollingSlot);
@@ -5798,14 +5808,15 @@ private void DataGrid_LostFocus(object sender, RoutedEventArgs e)
UpdateCurrentState(this.DisplayData.GetDisplayedElement(this.CurrentSlot), this.CurrentColumnIndex, true /*applyCellState*/);
}
}
- else if (!dataGridWillReceiveRoutedEvent)
- {
- FrameworkElement focusedElement = focusedObject as FrameworkElement;
- if (focusedElement != null)
- {
- focusedElement.LostFocus += new RoutedEventHandler(ExternalEditingElement_LostFocus);
- }
- }
+ }
+ }
+
+ private void HandleLostFocusForExternalElement(object focusedObject)
+ {
+ FrameworkElement focusedElement = focusedObject as FrameworkElement;
+ if (focusedElement != null)
+ {
+ focusedElement.LostFocus += new RoutedEventHandler(ExternalEditingElement_LostFocus);
}
}
@@ -8643,12 +8654,6 @@ private bool UpdateStateOnTapped(TappedRoutedEventArgs args, int columnIndex, in
{
_noSelectionChangeCount++;
- beginEdit = allowEdit &&
- this.CurrentSlot == slot &&
- columnIndex != -1 &&
- (wasInEdit || this.CurrentColumnIndex == columnIndex) &&
- !GetColumnEffectiveReadOnlyState(this.ColumnsItemsInternal[columnIndex]);
-
DataGridSelectionAction action;
if (this.SelectionMode == DataGridSelectionMode.Extended && shift)
{
@@ -8687,6 +8692,12 @@ private bool UpdateStateOnTapped(TappedRoutedEventArgs args, int columnIndex, in
}
UpdateSelectionAndCurrency(columnIndex, slot, action, false /*scrollIntoView*/);
+
+ beginEdit = allowEdit &&
+ this.CurrentSlot == slot &&
+ columnIndex != -1 &&
+ (wasInEdit || this.CurrentColumnIndex == columnIndex) &&
+ !GetColumnEffectiveReadOnlyState(this.ColumnsItemsInternal[columnIndex]);
}
finally
{