From cfa2462eef481e5fcfcf71320ee493c2c299b633 Mon Sep 17 00:00:00 2001 From: Waheed Ahmad Date: Wed, 4 Feb 2026 20:34:17 +0500 Subject: [PATCH 01/15] set options menu command in code behind --- src/TableView.Properties.cs | 15 +- src/TableViewHeaderRow.OptionComamnds.cs | 147 +++++++++++++++++ ...bleViewHeaderRow.OptionsFlyoutViewModel.cs | 149 ------------------ src/TableViewHeaderRow.cs | 29 +--- src/Themes/TableViewHeaderRow.xaml | 19 +-- 5 files changed, 169 insertions(+), 190 deletions(-) create mode 100644 src/TableViewHeaderRow.OptionComamnds.cs delete mode 100644 src/TableViewHeaderRow.OptionsFlyoutViewModel.cs diff --git a/src/TableView.Properties.cs b/src/TableView.Properties.cs index 6dbf992d..e9e46f24 100644 --- a/src/TableView.Properties.cs +++ b/src/TableView.Properties.cs @@ -58,7 +58,7 @@ public partial class TableView /// /// Identifies the ShowExportOptions dependency property. /// - public static readonly DependencyProperty ShowExportOptionsProperty = DependencyProperty.Register(nameof(ShowExportOptions), typeof(bool), typeof(TableView), new PropertyMetadata(false)); + public static readonly DependencyProperty ShowExportOptionsProperty = DependencyProperty.Register(nameof(ShowExportOptions), typeof(bool), typeof(TableView), new PropertyMetadata(false, OnShowExportOptionsChanged)); /// /// Identifies the AutoGenerateColumns dependency property. @@ -262,7 +262,7 @@ public partial class TableView /// /// Identifies the dependency property. /// - public static readonly DependencyProperty ShowFilterItemsCountProperty = DependencyProperty.Register(nameof(ShowFilterItemsCount), typeof(bool), typeof(TableView), new PropertyMetadata(false)); + public static readonly DependencyProperty ShowFilterItemsCountProperty = DependencyProperty.Register(nameof(ShowFilterItemsCount), typeof(bool), typeof(TableView), new PropertyMetadata(false)); /// /// Gets or sets a value indicating whether opening the column filter over header right-click is enabled. @@ -820,6 +820,17 @@ private static void OnSelectionModeChanged(DependencyObject d, DependencyPropert } } + /// + /// Handles changes to the ShowExportOptions property. + /// + private static void OnShowExportOptionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is TableView tableView) + { + tableView._headerRow?.SetExportOptionsVisibility(); + } + } + /// /// Handles changes to the AutoGenerateColumns property. /// diff --git a/src/TableViewHeaderRow.OptionComamnds.cs b/src/TableViewHeaderRow.OptionComamnds.cs new file mode 100644 index 00000000..76e0c9f6 --- /dev/null +++ b/src/TableViewHeaderRow.OptionComamnds.cs @@ -0,0 +1,147 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; + +namespace WinUI.TableView; + +partial class TableViewHeaderRow +{ + private MenuFlyoutItem? _exportAllMenuItem; + private MenuFlyoutItem? _exportSelectedMenuItem; + private readonly StandardUICommand _selectAllCommand = new(StandardUICommandKind.SelectAll) { Label = TableViewLocalizedStrings.SelectAll }; + private readonly StandardUICommand _deselectAllCommand = new() { Label = TableViewLocalizedStrings.DeselectAll }; + private readonly StandardUICommand _copyCommand = new(StandardUICommandKind.Copy) { Label = TableViewLocalizedStrings.Copy }; + private readonly StandardUICommand _copyWithHeadersCommand = new() { Label = TableViewLocalizedStrings.CopyWithHeaders }; + private readonly StandardUICommand _clearSortingCommand = new() { Label = TableViewLocalizedStrings.ClearSorting }; + private readonly StandardUICommand _clearFilterCommand = new() { Label = TableViewLocalizedStrings.ClearFilter }; + private readonly StandardUICommand _exportAllToCSVCommand = new() { Label = TableViewLocalizedStrings.ExportAll }; + private readonly StandardUICommand _exportSelectedToCSVCommand = new() { Label = TableViewLocalizedStrings.ExportSelected }; + + /// + /// Sets the visibility of the export options. + /// + internal void SetExportOptionsVisibility() + { + var visibility = TableView?.ShowExportOptions is true ? Visibility.Visible : Visibility.Collapsed; + + if (_exportAllMenuItem is not null) + { + _exportAllMenuItem.Visibility = visibility; + } + + if (_exportSelectedMenuItem is not null) + { + _exportSelectedMenuItem.Visibility = visibility; + } + } + + /// + /// Sets commands to option menu items. + /// + private void SetOptionMenuCommands() + { + InitializeCommands(); + + if (GetTemplateChild("SelectAllMenuItem") is MenuFlyoutItem selectAllMenuItem) + selectAllMenuItem.Command = _selectAllCommand; + if (GetTemplateChild("ClearSelectionMenuItem") is MenuFlyoutItem clearSelectionMenuItem) + clearSelectionMenuItem.Command = _deselectAllCommand; + if (GetTemplateChild("CopyMenuItem") is MenuFlyoutItem copyMenuItem) + copyMenuItem.Command = _copyCommand; + if (GetTemplateChild("CopyWithHeadersMenuItem") is MenuFlyoutItem copyWithHeadersMenuItem) + copyWithHeadersMenuItem.Command = _copyWithHeadersCommand; + if (GetTemplateChild("ClearSortingMenuItem") is MenuFlyoutItem clearSortingMenuItem) + clearSortingMenuItem.Command = _clearSortingCommand; + if (GetTemplateChild("ClearFilterMenuItem") is MenuFlyoutItem clearFilterMenuItem) + clearFilterMenuItem.Command = _clearFilterCommand; + if (GetTemplateChild("ExportAllMenuItem") is MenuFlyoutItem exportAllMenuItem) + { + _exportAllMenuItem = exportAllMenuItem; + exportAllMenuItem.Command = _exportAllToCSVCommand; + } + if (GetTemplateChild("ExportSelectedMenuItem") is MenuFlyoutItem exportSelectedMenuItem) + { + _exportSelectedMenuItem = exportSelectedMenuItem; + exportSelectedMenuItem.Command = _exportSelectedToCSVCommand; + } + } + + /// + /// Initializes the commands for the ViewModel. + /// + private void InitializeCommands() + { + _selectAllCommand.Description = TableViewLocalizedStrings.SelectAllCommandDescription; + _selectAllCommand.ExecuteRequested += delegate { TableView?.SelectAll(); }; + _selectAllCommand.CanExecuteRequested += CanExecuteSelectAllCommand; + + _deselectAllCommand.Description = TableViewLocalizedStrings.DeselectAllCommandDescription; + _deselectAllCommand.ExecuteRequested += delegate { TableView?.DeselectAll(); }; + _deselectAllCommand.CanExecuteRequested += CanExecuteDeselectAllCommand; + + _copyCommand.Description = TableViewLocalizedStrings.CopyCommandDescription; + _copyCommand.ExecuteRequested += ExecuteCopyCommand; + _copyCommand.CanExecuteRequested += CanExecuteCopyCommand; + + _copyWithHeadersCommand.Description = TableViewLocalizedStrings.CopyWithHeadersCommandDescription; + _copyWithHeadersCommand.ExecuteRequested += delegate { TableView?.CopyToClipboardInternal(true); }; + _copyWithHeadersCommand.CanExecuteRequested += CanExecuteCopyWithHeadersCommand; + + _clearSortingCommand.ExecuteRequested += delegate { TableView?.ClearAllSortingWithEvent(); }; + _clearSortingCommand.CanExecuteRequested += CanExecuteClearSortingCommand; + + _clearFilterCommand.ExecuteRequested += delegate { TableView?.FilterHandler.ClearFilter(default); }; + _clearFilterCommand.CanExecuteRequested += CanExecuteClearFilterCommand; + + _exportAllToCSVCommand.ExecuteRequested += delegate { TableView?.ExportAllToCSV(); }; + + _exportSelectedToCSVCommand.ExecuteRequested += delegate { TableView?.ExportSelectedToCSV(); }; + _exportSelectedToCSVCommand.CanExecuteRequested += CanExecuteExportSelectedToCSVCommand; + } + + private void CanExecuteSelectAllCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) + { + e.CanExecute = TableView?.IsEditing is false && TableView.SelectionMode is ListViewSelectionMode.Multiple or ListViewSelectionMode.Extended; + } + + private void CanExecuteDeselectAllCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) + { + e.CanExecute = TableView?.IsEditing is false && (TableView.SelectedItems.Count > 0 || TableView.SelectedCells.Count > 0); + } + + private void ExecuteCopyCommand(XamlUICommand sender, ExecuteRequestedEventArgs e) + { + var focusedElement = FocusManager.GetFocusedElement(TableView?.XamlRoot!); + if (focusedElement is FrameworkElement { Parent: TableViewCell }) + { + return; + } + + TableView?.CopyToClipboardInternal(false); + } + + private void CanExecuteCopyCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) + { + e.CanExecute = TableView?.SelectedItems.Count > 0 || TableView?.SelectedCells.Count > 0 || TableView?.CurrentCellSlot.HasValue is true; + } + + private void CanExecuteCopyWithHeadersCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) + { + e.CanExecute = TableView?.SelectedItems.Count > 0 || TableView?.SelectedCells.Count > 0 || TableView?.CurrentCellSlot.HasValue is true; + } + + private void CanExecuteClearSortingCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) + { + e.CanExecute = TableView?.IsEditing is false && TableView.IsSorted; + } + + private void CanExecuteClearFilterCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) + { + e.CanExecute = TableView?.IsEditing is false && TableView.IsFiltered; + } + + private void CanExecuteExportSelectedToCSVCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) + { + e.CanExecute = TableView?.IsEditing is false && (TableView.SelectedItems.Count > 0 || TableView.SelectedCells.Count > 0 || TableView.CurrentCellSlot.HasValue); + } +} diff --git a/src/TableViewHeaderRow.OptionsFlyoutViewModel.cs b/src/TableViewHeaderRow.OptionsFlyoutViewModel.cs deleted file mode 100644 index 26124c09..00000000 --- a/src/TableViewHeaderRow.OptionsFlyoutViewModel.cs +++ /dev/null @@ -1,149 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; -using System; - -namespace WinUI.TableView; - -public partial class TableViewHeaderRow -{ - /// - /// ViewModel for the options flyout in the TableViewHeaderRow. - /// - private class OptionsFlyoutViewModel - { - /// - /// Initializes a new instance of the OptionsFlyoutViewModel class. - /// - /// The TableView associated with the ViewModel. - public OptionsFlyoutViewModel(TableView _tableView) - { - InitializeCommands(); - TableView = _tableView; - } - - /// - /// Initializes the commands for the ViewModel. - /// - private void InitializeCommands() - { - SelectAllCommand.Description = TableViewLocalizedStrings.SelectAllCommandDescription; - SelectAllCommand.ExecuteRequested += delegate { TableView.SelectAll(); }; - SelectAllCommand.CanExecuteRequested += CanExecuteSelectAllCommand; - - DeselectAllCommand.Description = TableViewLocalizedStrings.DeselectAllCommandDescription; - DeselectAllCommand.ExecuteRequested += delegate { TableView.DeselectAll(); }; - DeselectAllCommand.CanExecuteRequested += CanExecuteDeselectAllCommand; - - CopyCommand.Description = TableViewLocalizedStrings.CopyCommandDescription; - CopyCommand.ExecuteRequested += ExecuteCopyCommand; - CopyCommand.CanExecuteRequested += CanExecuteCopyCommand; - - CopyWithHeadersCommand.Description = TableViewLocalizedStrings.CopyWithHeadersCommandDescription; - CopyWithHeadersCommand.ExecuteRequested += delegate { TableView.CopyToClipboardInternal(true); }; - CopyWithHeadersCommand.CanExecuteRequested += CanExecuteCopyWithHeadersCommand; - - ClearSortingCommand.ExecuteRequested += delegate { TableView.ClearAllSortingWithEvent(); }; - ClearSortingCommand.CanExecuteRequested += CanExecuteClearSortingCommand; - - ClearFilterCommand.ExecuteRequested += delegate { TableView.FilterHandler.ClearFilter(default); }; - ClearFilterCommand.CanExecuteRequested += CanExecuteClearFilterCommand; - - ExportAllToCSVCommand.ExecuteRequested += delegate { TableView.ExportAllToCSV(); }; - - ExportSelectedToCSVCommand.ExecuteRequested += delegate { TableView.ExportSelectedToCSV(); }; - ExportSelectedToCSVCommand.CanExecuteRequested += CanExecuteExportSelectedToCSVCommand; - } - - private void CanExecuteSelectAllCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) - { - e.CanExecute = !TableView.IsEditing && TableView.SelectionMode is ListViewSelectionMode.Multiple or ListViewSelectionMode.Extended; - } - - private void CanExecuteDeselectAllCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) - { - e.CanExecute = !TableView.IsEditing && (TableView.SelectedItems.Count > 0 || TableView.SelectedCells.Count > 0); - } - - private void ExecuteCopyCommand(XamlUICommand sender, ExecuteRequestedEventArgs e) - { - var focusedElement = FocusManager.GetFocusedElement(TableView.XamlRoot!); - if (focusedElement is FrameworkElement { Parent: TableViewCell }) - { - return; - } - - TableView.CopyToClipboardInternal(false); - } - - private void CanExecuteCopyCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) - { - e.CanExecute = TableView.SelectedItems.Count > 0 || TableView.SelectedCells.Count > 0 || TableView.CurrentCellSlot.HasValue; - } - - private void CanExecuteCopyWithHeadersCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) - { - e.CanExecute = TableView.SelectedItems.Count > 0 || TableView.SelectedCells.Count > 0 || TableView.CurrentCellSlot.HasValue; - } - - private void CanExecuteClearSortingCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) - { - e.CanExecute = !TableView.IsEditing && TableView.IsSorted; - } - - private void CanExecuteClearFilterCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) - { - e.CanExecute = !TableView.IsEditing && TableView.IsFiltered; - } - - private void CanExecuteExportSelectedToCSVCommand(XamlUICommand sender, CanExecuteRequestedEventArgs e) - { - e.CanExecute = !TableView.IsEditing && (TableView.SelectedItems.Count > 0 || TableView.SelectedCells.Count > 0 || TableView.CurrentCellSlot.HasValue); - } - - /// - /// Gets the command to select all rows. - /// - public StandardUICommand SelectAllCommand { get; } = new(StandardUICommandKind.SelectAll) { Label = TableViewLocalizedStrings.SelectAll }; - - /// - /// Gets the command to deselect all rows. - /// - public StandardUICommand DeselectAllCommand { get; } = new() { Label = TableViewLocalizedStrings.DeselectAll }; - - /// - /// Gets the command to copy the selected row's content to the clipboard. - /// - public StandardUICommand CopyCommand { get; } = new(StandardUICommandKind.Copy) { Label = TableViewLocalizedStrings.Copy }; - - /// - /// Gets the command to copy the selected row's content including column headers to the clipboard. - /// - public StandardUICommand CopyWithHeadersCommand { get; } = new() { Label = TableViewLocalizedStrings.CopyWithHeaders }; - - /// - /// Gets the command to clear sorting. - /// - public StandardUICommand ClearSortingCommand { get; } = new() { Label = TableViewLocalizedStrings.ClearSorting }; - - /// - /// Gets the command to clear filters. - /// - public StandardUICommand ClearFilterCommand { get; } = new() { Label = TableViewLocalizedStrings.ClearFilter }; - - /// - /// Gets the command to export all content to a CSV file. - /// - public StandardUICommand ExportAllToCSVCommand { get; } = new() { Label = TableViewLocalizedStrings.ExportAll }; - - /// - /// Gets the command to export selected content to a CSV file. - /// - public StandardUICommand ExportSelectedToCSVCommand { get; } = new() { Label = TableViewLocalizedStrings.ExportSelected }; - - /// - /// Gets the TableView associated with the ViewModel. - /// - public TableView TableView { get; } - } -} diff --git a/src/TableViewHeaderRow.cs b/src/TableViewHeaderRow.cs index 1224f92b..0a6bb040 100644 --- a/src/TableViewHeaderRow.cs +++ b/src/TableViewHeaderRow.cs @@ -70,11 +70,6 @@ protected override void OnApplyTemplate() return; } - if (_optionsButton is not null) - { - _optionsButton.DataContext = new OptionsFlyoutViewModel(TableView); - } - if (GetTemplateChild("selectAllButton") is Button selectAllButton) { selectAllButton.Tapped += OnSelectAllButtonClicked; @@ -97,6 +92,7 @@ protected override void OnApplyTemplate() Path = new PropertyPath(nameof(TableView.CellsHorizontalOffset)) }); + SetOptionMenuCommands(); SetExportOptionsVisibility(); SetCornerButtonState(); SetHeadersVisibility(); @@ -364,29 +360,6 @@ internal void CalculateHeaderWidths() } } - /// - /// Sets the visibility of the export options. - /// - private void SetExportOptionsVisibility() - { - var binding = new Binding - { - Path = new PropertyPath(nameof(TableView.ShowExportOptions)), - Source = TableView, - Converter = new BoolToVisibilityConverter() - }; - - if (GetTemplateChild("ExportAllMenuItem") is MenuFlyoutItem exportAll) - { - exportAll.SetBinding(VisibilityProperty, binding); - } - - if (GetTemplateChild("ExportSelectedMenuItem") is MenuFlyoutItem exportSelected) - { - exportSelected.SetBinding(VisibilityProperty, binding); - } - } - /// /// Handles the selection changed event for the TableView. /// diff --git a/src/Themes/TableViewHeaderRow.xaml b/src/Themes/TableViewHeaderRow.xaml index f68da69b..577a25d0 100644 --- a/src/Themes/TableViewHeaderRow.xaml +++ b/src/Themes/TableViewHeaderRow.xaml @@ -81,7 +81,6 @@ - public int Count { get; set; } - /// public override string ToString() { From 44fcc4211022315c3c3ecd190e96f6c4e4b00698 Mon Sep 17 00:00:00 2001 From: Waheed Ahmad Date: Fri, 6 Feb 2026 22:01:43 +0500 Subject: [PATCH 03/15] set filter flyout commands in code behind --- src/TableViewColumnHeader.OptionComamnds.cs | 70 +++++++++++++++++++++ src/Themes/TableViewColumnHeader.xaml | 14 ++--- 2 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 src/TableViewColumnHeader.OptionComamnds.cs diff --git a/src/TableViewColumnHeader.OptionComamnds.cs b/src/TableViewColumnHeader.OptionComamnds.cs new file mode 100644 index 00000000..a90976e9 --- /dev/null +++ b/src/TableViewColumnHeader.OptionComamnds.cs @@ -0,0 +1,70 @@ +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using WinUI.TableView.Extensions; +using SD = WinUI.TableView.SortDirection; + +namespace WinUI.TableView; + +partial class TableViewColumnHeader +{ + private readonly StandardUICommand _sortAscendingCommand = new() { Label = TableViewLocalizedStrings.SortAscending }; + private readonly StandardUICommand _sortDescendingCommand = new() { Label = TableViewLocalizedStrings.SortDescending }; + private readonly StandardUICommand _clearSortingCommand = new() { Label = TableViewLocalizedStrings.ClearSorting }; + private readonly StandardUICommand _clearFilterCommand = new() { Label = TableViewLocalizedStrings.ClearFilter }; + private readonly StandardUICommand _okCommand = new() { Label = TableViewLocalizedStrings.Ok }; + private readonly StandardUICommand _cancelCommand = new() { Label = TableViewLocalizedStrings.Cancel }; + + /// + /// Sets commands to option menu items. + /// + private void SetOptionCommands() + { + InitializeCommands(); + + if (GetTemplateChild("SortAscendingMenuItem") is MenuFlyoutItem sortAscendingMenuItem) + sortAscendingMenuItem.Command = _sortAscendingCommand; + if (GetTemplateChild("SortDescendingMenuItem") is MenuFlyoutItem sortDescendingMenuItem) + sortDescendingMenuItem.Command = _sortDescendingCommand; + if (GetTemplateChild("ClearSortingMenuItem") is MenuFlyoutItem clearSortingMenuItem) + clearSortingMenuItem.Command = _clearSortingCommand; + if (GetTemplateChild("ClearFilterMenuItem") is MenuFlyoutItem clearFilterMenuItem) + clearFilterMenuItem.Command = _clearFilterCommand; + if (GetTemplateChild("ActionButtonsMenuItem") is MenuFlyoutItem actionButtonsMenuItem) + { + actionButtonsMenuItem.ApplyTemplate(); + + if (actionButtonsMenuItem.FindDescendant + + + + + \ No newline at end of file From ee37b202219e154d49d58004888127869e91c6ce Mon Sep 17 00:00:00 2001 From: Waheed Ahmad Date: Wed, 22 Apr 2026 01:34:47 +0500 Subject: [PATCH 14/15] update aot test app --- samples/AotTestApp/BlankPage1.xaml | 20 ++----- samples/AotTestApp/BlankPage1.xaml.cs | 2 +- samples/AotTestApp/DataFaker.cs | 78 +++++++++++++-------------- samples/AotTestApp/ExampleModel.cs | 25 ++++++++- samples/AotTestApp/MainViewModel.cs | 24 +++++---- 5 files changed, 82 insertions(+), 67 deletions(-) diff --git a/samples/AotTestApp/BlankPage1.xaml b/samples/AotTestApp/BlankPage1.xaml index ea436847..089b6dd5 100644 --- a/samples/AotTestApp/BlankPage1.xaml +++ b/samples/AotTestApp/BlankPage1.xaml @@ -9,23 +9,15 @@ - - - - - - - @@ -36,18 +28,16 @@ Binding="{Binding User.Email}" /> - + ContentBinding="{Binding User.FirstName}" /> diff --git a/samples/AotTestApp/BlankPage1.xaml.cs b/samples/AotTestApp/BlankPage1.xaml.cs index 554a126f..d5881fe9 100644 --- a/samples/AotTestApp/BlankPage1.xaml.cs +++ b/samples/AotTestApp/BlankPage1.xaml.cs @@ -1,3 +1,4 @@ +using ABI.System; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls.Primitives; @@ -32,5 +33,4 @@ public BlankPage1() } public MainViewModel ViewModel { get; } - } diff --git a/samples/AotTestApp/DataFaker.cs b/samples/AotTestApp/DataFaker.cs index 53979988..da9fb7c0 100644 --- a/samples/AotTestApp/DataFaker.cs +++ b/samples/AotTestApp/DataFaker.cs @@ -35,47 +35,47 @@ public static class DataFaker ]; // Job titles - public static readonly Designation[] JobTitles = + internal static readonly string[] JobTitles = [ - new(1,"Software Developer"), - new(2,"Manager"), - new(3,"Sales Representative") , - new(4,"Accountant") , - new(5,"Analyst"), - new(6,"Engineer"), - new(7,"Designer"), - new(8,"Teacher"), - new(9,"Consultant"), - new(10,"Executive"), - new(11,"Administrator"), - new(12,"Coordinator"), - new(13,"Director"), - new(14,"Supervisor"), - new(15,"Specialist"), - new(16,"Technician"), - new(17,"Operator"), - new(18,"Clerk"), - new(19,"Assistant"), - new(20,"Officer"), - new(21,"Agent"), - new(22,"Associate"), - new(23,"Architect"), - new(24,"Planner"), - new(25,"Scientist"), - new(26,"Researcher"), - new(27,"Programmer"), - new(28,"Nurse"), - new(29,"Doctor"), - new(30,"Lawyer"), - new(31,"Marketing Manager"), - new(32,"Product Manager"), - new(33,"Business Analyst"), - new(34,"Data Scientist"), - new(35,"DevOps Engineer") + "Software Developer", + "Manager", + "Sales Representative", + "Accountant", + "Analyst", + "Engineer", + "Designer", + "Teacher", + "Consultant", + "Executive", + "Administrator", + "Coordinator", + "Director", + "Supervisor", + "Specialist", + "Technician", + "Operator", + "Clerk", + "Assistant", + "Officer", + "Agent", + "Associate", + "Architect", + "Planner", + "Scientist", + "Researcher", + "Programmer", + "Nurse", + "Doctor", + "Lawyer", + "Marketing Manager", + "Product Manager", + "Business Analyst", + "Data Scientist", + "DevOps Engineer" ]; // Department names - private static readonly string[] Departments = + internal static readonly string[] Departments = [ "Sales", "Marketing", "Engineering", "Finance", "Human Resources", "Operations", "IT", "Legal", "Research", "Development", @@ -114,7 +114,7 @@ public static class DataFaker ]; // Genders - private static readonly string[] Genders = ["Male", "Female", "Non-binary", "Genderfluid", "Agender", "Bigender", "Genderqueer", "Two-Spirit", "Prefer not to say"]; + internal static readonly string[] Genders = ["Male", "Female", "Non-binary", "Genderfluid", "Agender", "Bigender", "Genderqueer", "Two-Spirit", "Prefer not to say"]; // Avatar images (using placeholder service URLs) private static readonly string[] AvatarSeeds = @@ -189,7 +189,7 @@ public static string Department() return Departments[_random.Next(Departments.Length)]; } - public static Designation JobTitle() + public static string JobTitle() { return JobTitles[_random.Next(JobTitles.Length)]; } diff --git a/samples/AotTestApp/ExampleModel.cs b/samples/AotTestApp/ExampleModel.cs index a06d5db2..4a453f20 100644 --- a/samples/AotTestApp/ExampleModel.cs +++ b/samples/AotTestApp/ExampleModel.cs @@ -14,7 +14,6 @@ public Designation(int id, string? title) [ObservableProperty] public partial int Id { get; set; } - [ObservableProperty] public partial string? Title { get; set; } } @@ -39,6 +38,25 @@ public partial class User : ObservableObject public partial DateOnly Dob { get; set; } } +public partial class DateTimeModel : ObservableObject +{ + + [ObservableProperty] + public partial TimeSpan TimeSpan1 { get; set; } + + [ObservableProperty] + public partial TimeOnly TimeOnly1 { get; set; } + + [ObservableProperty] + public partial DateOnly DateOnly1 { get; set; } + + [ObservableProperty] + public partial DateTime DateTime1 { get; set; } + + [ObservableProperty] + public partial DateTimeOffset DateTimeOffset1 { get; set; } +} + public partial class ExampleModel : ObservableObject { [ObservableProperty] @@ -56,7 +74,7 @@ public partial class ExampleModel : ObservableObject public partial string? Department { get; set; } [ObservableProperty] - public partial Designation? Designation { get; set; } + public partial string? Designation { get; set; } [ObservableProperty] public partial string? Address { get; set; } @@ -70,4 +88,7 @@ public partial class ExampleModel : ObservableObject [ObservableProperty] [Display(AutoGenerateField = false)] public partial User? User { get; set; } + + [ObservableProperty] + public partial DateTimeModel? DateTimeModel { get; set; } } diff --git a/samples/AotTestApp/MainViewModel.cs b/samples/AotTestApp/MainViewModel.cs index 3eb10c13..d69ae030 100644 --- a/samples/AotTestApp/MainViewModel.cs +++ b/samples/AotTestApp/MainViewModel.cs @@ -13,11 +13,7 @@ public MainViewModel() foreach (var item in ItemsList) { Items.Add(item); - Genders.Add(item.User?.Gender); - Departments.Add(item.Department); } - - Designations = [.. DataFaker.JobTitles]; } public static void InitializeItems() @@ -34,7 +30,7 @@ public static void InitializeItems() var email = DataFaker.Email(firstName, lastName); var gender = DataFaker.Gender(); var dob = DataFaker.PastDate(50, startDate); - ItemsList.Add(new ExampleModel + var item = new ExampleModel { Id = startId++, IsActive = DataFaker.Boolean(), @@ -50,8 +46,17 @@ public static void InitializeItems() Email = email, Gender = gender, Dob = dob + }, + DateTimeModel = new DateTimeModel + { + TimeSpan1 = DataFaker.TimeOfDay().ToTimeSpan(), + TimeOnly1 = DataFaker.TimeOfDay(), + DateTime1 = new DateTime(DataFaker.PastDate(50, dob), DataFaker.TimeOfDay()), + DateTimeOffset1 = new DateTimeOffset(DataFaker.PastDate(50, dob), DataFaker.TimeOfDay(), TimeSpan.Zero), + DateOnly1 = DataFaker.PastDate(50, dob) } - }); + }; + ItemsList.Add(item); } } @@ -60,12 +65,11 @@ public static void InitializeItems() [ObservableProperty] public partial ObservableCollection Items { get; set; } = []; - public IList Genders { get; set; } = []; - - public IList Departments { get; set; } = []; + public List Genders => [.. DataFaker.Genders]; - public IList Designations { get; set; } = []; + public List Departments => [.. DataFaker.Departments]; + public List Designations => [.. DataFaker.JobTitles]; [ObservableProperty] public partial ExampleModel? SelectedItem { get; set; } } From 77017743d14731f5baf105217545d9d747c2ed24 Mon Sep 17 00:00:00 2001 From: Waheed Ahmad Date: Wed, 22 Apr 2026 02:19:57 +0500 Subject: [PATCH 15/15] Refactor MemberValueProvider to CellValueProvider --- generators/TableViewBindingProviderGenerator.cs | 6 +++--- src/Columns/TableViewBoundColumn.cs | 4 ++-- src/Columns/TableViewColumn.cs | 2 +- src/Columns/TableViewComboBoxColumn.cs | 2 +- src/Columns/TableViewDateColumn.cs | 3 +++ src/Columns/TableViewHyperlinkColumn.cs | 2 +- src/{ITableViewValuesProvider.cs => ICellValueProvider.cs} | 1 + src/ItemsSource/ColumnSortDescription.cs | 2 +- src/TableView.Properties.cs | 2 +- src/TableView.cs | 2 +- 10 files changed, 15 insertions(+), 11 deletions(-) rename src/{ITableViewValuesProvider.cs => ICellValueProvider.cs} (99%) diff --git a/generators/TableViewBindingProviderGenerator.cs b/generators/TableViewBindingProviderGenerator.cs index 5bdb426e..236c013d 100644 --- a/generators/TableViewBindingProviderGenerator.cs +++ b/generators/TableViewBindingProviderGenerator.cs @@ -290,7 +290,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) continue; } - var baseProviderClassName = $"TableView_{SanitizeIdentifier(tableView.TableViewName!)}_MemberValueProvider"; + var baseProviderClassName = $"TableView_{SanitizeIdentifier(tableView.TableViewName!)}_CellValueProvider"; var providerClassName = GetUniqueIdentifier(baseProviderClassName, usedProviderClassNames); providers.Add(new GeneratedProviderInfo( @@ -1760,7 +1760,7 @@ private static string BuildSource( .Append(provider.TableViewName) .AppendLine("))"); builder.AppendLine(" {"); - builder.Append(" @param_tableView.MemberValueProvider = new ") + builder.Append(" @param_tableView.CellValueProvider = new ") .Append(provider.ProviderClassName) .AppendLine("();"); builder.AppendLine(" }"); @@ -1775,7 +1775,7 @@ private static string BuildSource( { builder.Append(" this.") .Append(provider.TableViewName) - .Append(".MemberValueProvider = new ") + .Append(".CellValueProvider = new ") .Append(provider.ProviderClassName) .AppendLine("();"); } diff --git a/src/Columns/TableViewBoundColumn.cs b/src/Columns/TableViewBoundColumn.cs index 5e4c127d..21cadf50 100644 --- a/src/Columns/TableViewBoundColumn.cs +++ b/src/Columns/TableViewBoundColumn.cs @@ -19,7 +19,7 @@ public abstract class TableViewBoundColumn : TableViewColumn /// public override object? GetCellContent(object? dataItem) { - if (TableView?.MemberValueProvider is { } provider && + if (TableView?.CellValueProvider is { } provider && provider.TryGetBindingValue(PropertyPath, dataItem, out var value)) { return BindingHelper.ConvertValue(Binding, value); @@ -55,7 +55,7 @@ public virtual void TrySetBindingValue(object? dataItem, object? value) { var convertedValue = BindingHelper.ConvertBackValue(Binding, value); - if (TableView?.MemberValueProvider is { } provider) + if (TableView?.CellValueProvider is { } provider) { provider.TrySetBindingValue(PropertyPath, dataItem, convertedValue); } diff --git a/src/Columns/TableViewColumn.cs b/src/Columns/TableViewColumn.cs index 278c550e..8951ed3b 100644 --- a/src/Columns/TableViewColumn.cs +++ b/src/Columns/TableViewColumn.cs @@ -119,7 +119,7 @@ internal void SetOwningTableView(TableView tableView) /// The clipboard content of the cell. public virtual object? GetClipboardContent(object? dataItem) { - if (TableView?.MemberValueProvider is { } provider && + if (TableView?.CellValueProvider is { } provider && provider.TryGetClipboardContentBindingValue(ClipboardContentBindingPropertyPath, dataItem, out var value)) { return BindingHelper.ConvertValue(ClipboardContentBinding, value); diff --git a/src/Columns/TableViewComboBoxColumn.cs b/src/Columns/TableViewComboBoxColumn.cs index 5582c3cc..6c51b81f 100644 --- a/src/Columns/TableViewComboBoxColumn.cs +++ b/src/Columns/TableViewComboBoxColumn.cs @@ -38,7 +38,7 @@ public override FrameworkElement GenerateElement(TableViewCell cell, object? dat /// protected virtual string? GetDisplayValue(object? dataItem) { - if (TableView?.MemberValueProvider is { } provider && + if (TableView?.CellValueProvider is { } provider && provider.TryGetDisplayMemberValue(DisplayMemberPath, dataItem, out var value)) { return value?.ToString(); diff --git a/src/Columns/TableViewDateColumn.cs b/src/Columns/TableViewDateColumn.cs index 0b174803..af6d85c5 100644 --- a/src/Columns/TableViewDateColumn.cs +++ b/src/Columns/TableViewDateColumn.cs @@ -19,6 +19,9 @@ namespace WinUI.TableView; #endif public partial class TableViewDateColumn : TableViewBoundColumn { + /// + /// Default date format used for displaying the date in the cell when DateFormat is not set. + /// public const string DefaultDateFormat = "shortdate"; /// diff --git a/src/Columns/TableViewHyperlinkColumn.cs b/src/Columns/TableViewHyperlinkColumn.cs index 0a227f20..52435110 100644 --- a/src/Columns/TableViewHyperlinkColumn.cs +++ b/src/Columns/TableViewHyperlinkColumn.cs @@ -64,7 +64,7 @@ public override FrameworkElement GenerateElement(TableViewCell cell, object? dat /// The content for the HyperlinkButton. protected virtual object? GetContent(object? dataItem) { - if (TableView?.MemberValueProvider is { } provider && + if (TableView?.CellValueProvider is { } provider && provider.TryGetContentBindingValue(ContentBinding?.Path?.Path, dataItem, out var value)) { return value; diff --git a/src/ITableViewValuesProvider.cs b/src/ICellValueProvider.cs similarity index 99% rename from src/ITableViewValuesProvider.cs rename to src/ICellValueProvider.cs index 6234a4be..61a5ba13 100644 --- a/src/ITableViewValuesProvider.cs +++ b/src/ICellValueProvider.cs @@ -59,3 +59,4 @@ public interface ICellValueProvider /// when a value was resolved; otherwise . bool TryGetDisplayMemberValue(string? path, object? item, out object? value); } + diff --git a/src/ItemsSource/ColumnSortDescription.cs b/src/ItemsSource/ColumnSortDescription.cs index e2c7d627..4bd3dead 100644 --- a/src/ItemsSource/ColumnSortDescription.cs +++ b/src/ItemsSource/ColumnSortDescription.cs @@ -29,7 +29,7 @@ public ColumnSortDescription(TableViewColumn column, // Use reflection-based property access when SortMemberPath is explicitly provided; otherwise, fall back to column cell content. if (!string.IsNullOrEmpty(Column.SortMemberPath)) { - if (Column.TableView?.MemberValueProvider is { } provider + if (Column.TableView?.CellValueProvider is { } provider && provider.TryGetSortMemberValue(Column.SortMemberPath, item, out var value)) { return value; diff --git a/src/TableView.Properties.cs b/src/TableView.Properties.cs index 63aa7637..29153f9f 100644 --- a/src/TableView.Properties.cs +++ b/src/TableView.Properties.cs @@ -374,7 +374,7 @@ public bool ShowFilterItemsCount /// /// Gets or sets the provider used to resolve values. /// - public ICellValueProvider? MemberValueProvider { get; set; } + public ICellValueProvider? CellValueProvider { get; set; } /// /// Gets a value indicating whether the TableView items are filtered. diff --git a/src/TableView.cs b/src/TableView.cs index 6f6cba76..85b406c1 100644 --- a/src/TableView.cs +++ b/src/TableView.cs @@ -302,7 +302,7 @@ protected async override void OnApplyTemplate() SetHeadersVisibility(); - if (MemberValueProvider is null) + if (CellValueProvider is null) { // Connect this TableView instance to avoid re-connecting unrelated TableViews. this.FindAscendant()?.ConnectTableView(this);