diff --git a/src/WinUI.TableView/TableView.Properties.cs b/src/WinUI.TableView/TableView.Properties.cs index 87fb8f9..b3d8961 100644 --- a/src/WinUI.TableView/TableView.Properties.cs +++ b/src/WinUI.TableView/TableView.Properties.cs @@ -1,6 +1,7 @@ using CommunityToolkit.WinUI.Collections; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Media; using System; using System.Collections; @@ -32,6 +33,8 @@ public partial class TableView public static readonly DependencyProperty VerticalGridLinesStrokeProperty = DependencyProperty.Register(nameof(VerticalGridLinesStroke), typeof(Brush), typeof(TableView), new PropertyMetadata(default, OnGridLinesPropertyChanged)); public static readonly DependencyProperty AlternateRowForegroundProperty = DependencyProperty.Register(nameof(AlternateRowForeground), typeof(Brush), typeof(TableView), new PropertyMetadata(null, OnAlternateRowColorChanged)); public static readonly DependencyProperty AlternateRowBackgroundProperty = DependencyProperty.Register(nameof(AlternateRowBackground), typeof(Brush), typeof(TableView), new PropertyMetadata(null, OnAlternateRowColorChanged)); + public static readonly DependencyProperty RowContextFlyoutProperty = DependencyProperty.Register(nameof(RowContextFlyout), typeof(FlyoutBase), typeof(TableView), new PropertyMetadata(null)); + public static readonly DependencyProperty CellContextFlyoutProperty = DependencyProperty.Register(nameof(CellContextFlyout), typeof(FlyoutBase), typeof(TableView), new PropertyMetadata(null)); public IAdvancedCollectionView CollectionView { get; private set; } = new AdvancedCollectionView(); internal IDictionary> ActiveFilters { get; } = new Dictionary>(); @@ -184,6 +187,18 @@ public Brush AlternateRowForeground set => SetValue(AlternateRowForegroundProperty, value); } + public FlyoutBase? RowContextFlyout + { + get => (FlyoutBase?)GetValue(RowContextFlyoutProperty); + set => SetValue(RowContextFlyoutProperty, value); + } + + public FlyoutBase? CellContextFlyout + { + get => (FlyoutBase?)GetValue(CellContextFlyoutProperty); + set => SetValue(CellContextFlyoutProperty, value); + } + private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is TableView tableView) diff --git a/src/WinUI.TableView/TableView.cs b/src/WinUI.TableView/TableView.cs index 09036b5..08526d9 100644 --- a/src/WinUI.TableView/TableView.cs +++ b/src/WinUI.TableView/TableView.cs @@ -1074,11 +1074,49 @@ private void EnsureAlternateRowColors() } } + internal void ShowRowContext(TableViewRow row, Point position) + { + if (RowContextFlyout is null) return; + + var eventArgs = new TableViewRowContextFlyoutEventArgs(row.Index, row, row.Content, RowContextFlyout); + RowContextFlyoutOpening?.Invoke(this, eventArgs); + + if (!eventArgs.Handled) + { + RowContextFlyout.ShowAt(row, new FlyoutShowOptions + { + ShowMode = FlyoutShowMode.Standard, + Placement = RowContextFlyout.Placement, + Position = position + }); + } + } + + internal void ShowCellContext(TableViewCell cell, Point position) + { + if (CellContextFlyout is null) return; + + var eventArgs = new TableViewCellContextFlyoutEventArgs(cell.Slot, cell, cell.Row?.Content!, CellContextFlyout); + CellContextFlyoutOpening?.Invoke(this, eventArgs); + + if (!eventArgs.Handled) + { + CellContextFlyout.ShowAt(cell, new FlyoutShowOptions + { + ShowMode = FlyoutShowMode.Standard, + Placement = CellContextFlyout.Placement, + Position = position + }); + } + } + public event EventHandler? AutoGeneratingColumn; public event EventHandler? ExportAllContent; public event EventHandler? ExportSelectedContent; public event EventHandler? CopyToClipboard; public event DependencyPropertyChangedEventHandler? IsReadOnlyChanged; + public event EventHandler? RowContextFlyoutOpening; + public event EventHandler? CellContextFlyoutOpening; internal event EventHandler? SelectedCellsChanged; internal event EventHandler? CurrentCellChanged; diff --git a/src/WinUI.TableView/TableViewCell.cs b/src/WinUI.TableView/TableViewCell.cs index 509f2b0..8071aad 100644 --- a/src/WinUI.TableView/TableViewCell.cs +++ b/src/WinUI.TableView/TableViewCell.cs @@ -31,6 +31,15 @@ public TableViewCell() DefaultStyleKey = typeof(TableViewCell); ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY; Loaded += OnLoaded; + ContextRequested += OnContextRequested; + } + + private void OnContextRequested(UIElement sender, ContextRequestedEventArgs args) + { + if (TableView is not null && args.TryGetPosition(sender, out var position)) + { + TableView.ShowCellContext(this, position); + } } private void OnLoaded(object sender, RoutedEventArgs e) diff --git a/src/WinUI.TableView/TableViewCellContextFlyoutEventArgs.cs b/src/WinUI.TableView/TableViewCellContextFlyoutEventArgs.cs new file mode 100644 index 0000000..89d760c --- /dev/null +++ b/src/WinUI.TableView/TableViewCellContextFlyoutEventArgs.cs @@ -0,0 +1,20 @@ +using Microsoft.UI.Xaml.Controls.Primitives; +using System.ComponentModel; + +namespace WinUI.TableView; + +public partial class TableViewCellContextFlyoutEventArgs : HandledEventArgs +{ + public TableViewCellContextFlyoutEventArgs(TableViewCellSlot slot, TableViewCell cell, object item, FlyoutBase flyout) + { + Slot = slot; + Cell = cell; + Item = item; + Flyout = flyout; + } + + public TableViewCellSlot Slot { get; } + public TableViewCell Cell { get; } + public object Item { get; } + public FlyoutBase Flyout { get; } +} diff --git a/src/WinUI.TableView/TableViewCellSlot.cs b/src/WinUI.TableView/TableViewCellSlot.cs index fc09909..0f0c662 100644 --- a/src/WinUI.TableView/TableViewCellSlot.cs +++ b/src/WinUI.TableView/TableViewCellSlot.cs @@ -1,2 +1,2 @@ namespace WinUI.TableView; -internal readonly record struct TableViewCellSlot(int Row, int Column); +public readonly record struct TableViewCellSlot(int Row, int Column); diff --git a/src/WinUI.TableView/TableViewRow.cs b/src/WinUI.TableView/TableViewRow.cs index cf0f0ae..47fe681 100644 --- a/src/WinUI.TableView/TableViewRow.cs +++ b/src/WinUI.TableView/TableViewRow.cs @@ -32,9 +32,33 @@ public TableViewRow() SizeChanged += OnSizeChanged; Loaded += TableViewRow_Loaded; + ContextRequested += OnContextRequested; RegisterPropertyChangedCallback(IsSelectedProperty, delegate { OnIsSelectedChanged(); }); } + private void OnContextRequested(UIElement sender, ContextRequestedEventArgs args) + { + if (args.TryGetPosition(sender, out var position)) + { + if (IsContextRequestedFromCell(position) && TableView?.CellContextFlyout is not null) return; + + + TableView?.ShowRowContext(this, position); + } + } + + private bool IsContextRequestedFromCell(Windows.Foundation.Point position) + { + if (_cellPresenter is null) return false; + + var transform = _cellPresenter.TransformToVisual(this).Inverse; + var point = transform.TransformPoint(position); + var transformedPoint = _cellPresenter.TransformToVisual(null).TransformPoint(point); + return VisualTreeHelper.FindElementsInHostCoordinates(transformedPoint, _cellPresenter) + .OfType() + .Any(); + } + private void OnIsSelectedChanged() { DispatcherQueue.TryEnqueue(() => diff --git a/src/WinUI.TableView/TableViewRowContextFlyoutEventArgs.cs b/src/WinUI.TableView/TableViewRowContextFlyoutEventArgs.cs new file mode 100644 index 0000000..20bbe44 --- /dev/null +++ b/src/WinUI.TableView/TableViewRowContextFlyoutEventArgs.cs @@ -0,0 +1,20 @@ +using Microsoft.UI.Xaml.Controls.Primitives; +using System.ComponentModel; + +namespace WinUI.TableView; + +public partial class TableViewRowContextFlyoutEventArgs : HandledEventArgs +{ + public TableViewRowContextFlyoutEventArgs(int index, TableViewRow row, object item, FlyoutBase flyout) + { + Index = index; + Row = row; + Item = item; + Flyout = flyout; + } + + public int Index { get; } + public TableViewRow Row { get; } + public object Item { get; } + public FlyoutBase Flyout { get; } +}