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 {