From c1acfb3b9973a2c0e05acd6a48394faf00c728d6 Mon Sep 17 00:00:00 2001 From: AARTHI Date: Mon, 13 Oct 2025 12:18:31 +0530 Subject: [PATCH 1/7] 986416-Added UG content for Maui SfKanban sorting feature and ImageEditor AnnotationsDeserialized event support --- MAUI/ImageEditor/events.md | 28 +++ MAUI/Kanban-Board/Sorting.md | 456 +++++++++++++++++++++++++++++++++++ maui-toc.html | 3 +- 3 files changed, 486 insertions(+), 1 deletion(-) create mode 100644 MAUI/Kanban-Board/Sorting.md diff --git a/MAUI/ImageEditor/events.md b/MAUI/ImageEditor/events.md index 2ed2296b91..6afc124a3a 100644 --- a/MAUI/ImageEditor/events.md +++ b/MAUI/ImageEditor/events.md @@ -87,3 +87,31 @@ The [`BrowseImage`](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.ImageEdi {% endhighlight %} {% endtabs %} + +## AnnotationsDeserialized event + +The 'AnnotationsDeserialized' event is triggered each time deserialization completes and annotations are applied to the ImageEditor control. This allows users to validate the data, update the UI, or execute custom business logic. + +N> Serialization and deserialization are not applicable for custom annotation views. + +{% tabs %} + +{% highlight xaml tabtitle="MainPage.xaml" %} + + + +{% endhighlight %} + +{% highlight C# tabtitle="MainPage.xaml.cs" %} + + private void OnAnnotationsDeserialized(object? sender, EventArgs e) + { + + // Add anything here, like dispaly alert to show event raised + } + +{% endhighlight %} + +{% endtabs %} diff --git a/MAUI/Kanban-Board/Sorting.md b/MAUI/Kanban-Board/Sorting.md new file mode 100644 index 0000000000..61e7d4ea80 --- /dev/null +++ b/MAUI/Kanban-Board/Sorting.md @@ -0,0 +1,456 @@ +--- +layout: post +title: Sorting in .NET MAUI Kanban control | Syncfusion +description: Learn here all about Sorting support in Syncfusion® .NET MAUI Kanban (SfKanban) control and more. +platform: maui +control: Kanban +documentation: ug +keywords: .net maui Kanban sorting, sfKanban sorting in .net maui, .net maui Kanban sorting support. +--- + +# Sorting in .NET MAUI Kanban (SfKanban) + +This feature is used to sort the card items on Kanban Columns by following below properties + +* `SortingMappingPath` - This property should correspond to a property name in the KanbanModel or CustomModel. The default value is string.Empty in this case the cards won’t be sorted. +* `SortingOrder` - Defines the order in which cards appear. The default is Ascending. + * `Ascending` - Cards with lower values appear first. + * `Descending` - Cards with higher values appear first. + +## Cards position updation while drag and drop + +In the SfKanban Sorting feature, you can customize how cards are sorted during drag-and-drop actions. When a card is dropped, its position in the target column is updated based on the SortingMappingPath value. + +The following code example describes the card position changing functionality. + +{% tabs %} +{% highlight XAML hl_lines="3" %} + + + + + + + +{% endhighlight %} + +{% highlight C# hl_lines="2" %} + +this.kanban.ItemsSource = new SortingViewModel().Cards; +this.kanban.DragEnd += this.OnCardDragEnd; + +private void OnCardDragEnd(object? sender, KanbanDragEndEventArgs e) +{ + this.kanban.RefreshKanbanColumn(); +} + +{% endhighlight %} + +{% highlight c# tabtitle="CardDetails.cs" %} + +public class CardDetails : INotifyPropertyChanged +{ + #region Fields + + /// + /// The title of the card. + /// + private string? _title; + + /// + /// The description of the card. + /// + private string? _description; + + /// + /// The category of the card. This property is used for column mapping in the Kanban board. + /// + private string? _category; + + /// + /// The list of tags associated with the card. + /// + private List? _tags; + + /// + /// The index of the card. This property is used for sorting the cards within a column. + /// + private int _index; + + /// + /// The priority of the card. This property can be used for additional sorting or filtering. + /// + private Priority? _priority; + + /// + /// The value of the progresbar on each card item. + /// + private double _progress; + + #endregion + + #region Properties + + /// + /// Gets or sets the title of the card. + /// + public string? Title + { + get { return this._title; } + set + { + this._title = value; + this.OnPropertyChanged(nameof(Title)); + } + } + + /// + /// Gets or sets the description of the card. + /// + public string? Description + { + get { return this._description; } + set + { + this._description = value; + this.OnPropertyChanged(nameof(Description)); + } + } + + /// + /// Gets or sets the category of the card. This property is used for column mapping in the Kanban board. + /// + public string? Category + { + get { return this._category; } + set + { + this._category = value; + this.OnPropertyChanged(nameof(Category)); + } + } + + /// + /// Gets or sets the list of tags associated with the card. + /// + public List? Tags + { + get { return this._tags; } + set + { + this._tags = value; + this.OnPropertyChanged(nameof(Tags)); + } + } + + /// + /// Gets or sets the index of the card. This property is used for sorting the cards within a column. + /// + public int Index + { + get { return this._index; } + set + { + this._index = value; + this.OnPropertyChanged(nameof(Index)); + } + } + + /// + /// Gets or sets the priority of the card. This property can be used for additional sorting or filtering. + /// + public Priority? Priority + { + get { return this._priority; } + set + { + this._priority = value; + this.OnPropertyChanged(nameof(Priority)); + } + } + + /// + /// Gets or sets the ProgressBar value associated with the card. + /// + public double Progress + { + get { return this._progress; } + set + { + if (this._progress != value) + { + this._progress = value; + this.OnPropertyChanged(nameof(Progress)); + } + } + } + + #endregion + + #region Event + + /// + /// Occurs when a property value changes. + /// + public event PropertyChangedEventHandler? PropertyChanged; + + #endregion + + #region Methods + + /// + /// Invokes the event when the value of a property has changed. + /// + /// The name of the property that has changed. + private void OnPropertyChanged(string propertyName) + { + this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + #endregion +} + +{% endhighlight %} + +{% highlight c# tabtitle="SortingViewModel.cs" %} + +public class SortingViewModel +{ + #region Constructor + + /// + /// Initializes a new instance of the class. + /// + public SortingViewModel() + { + this.Cards = this.GetCardDetails(); + } + + #endregion + + #region Properties + + /// + /// Gets or sets the collection of objects representing cards in various stages. + /// + public ObservableCollection Cards { get; set; } + + #endregion + + #region Private method + + /// + /// Method to retrieve a predefined collection of Kanban cards with sorting metadata. + /// + /// The card collection. + private ObservableCollection GetCardDetails() + { + var cardDetails = new ObservableCollection(); + cardDetails.Add(new CardDetails() + { + Index = 5, + Priority = Priority.Medium, + Title = "Task - 1", + Category = "Open", + Description = "Fix the issue reported in the Edge browser.", + Progress = 0, + Tags = new List { "Analyze", "Bug" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 2, + Title = "Task - 3", + Priority = Priority.Low, + Category = "Open", + Description = "Analyze the new requirements gathered from the customer.", + Progress = 0, + Tags = new List { "Trial preparation" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 3, + Title = "Task - 4", + Priority = Priority.Critical, + Category = "Open", + Description = "Arrange a web meeting with the customer to get new requirements.", + Progress = 0, + Tags = new List { "Litigation support" } + }); + + cardDetails.Add(new CardDetails() + { + Title = "Task - 2", + Priority = Priority.High, + Index = 4, + Category = "In Progress", + Description = "Test the application in the Edge browser.", + Progress = 40, + Tags = new List { "Documentation" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 1, + Title = "Task - 5", + Priority = Priority.Medium, + Category = "Open", + Description = "Enhance editing functionality.", + Progress = 0, + Tags = new List { "Analyze" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 7, + Title = "Task - 6", + Priority = Priority.Low, + Category = "Open", + Description = "Arrange web meeting with the customer to show editing demo.", + Progress = 0, + Tags = new List { "Bug" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 6, + Title = "Task - 8", + Priority = Priority.Medium, + Category = "Done", + Description = "Improve application performance.", + Progress = 100, + Tags = new List { "Litigation support" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 10, + Title = "Task - 7", + Priority = Priority.Critical, + Category = "In Progress", + Description = "Fix cannot open user's default database SQL error.", + Progress = 50, + Tags = new List { "Trial preparation" } + }); + + cardDetails.Add(new CardDetails() + { + Title = "Task - 9", + Priority = Priority.Medium, + Index = 8, + Category = "In Progress", + Description = "Improve the performance of the editing functionality.", + Progress = 55, + Tags = new List { "Bug" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 9, + Title = "Task - 10", + Priority = Priority.High, + Category = "Done", + Description = "Analyze grid control.", + Progress = 100, + Tags = new List { "Documentation" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 15, + Title = "Task - 12", + Priority = Priority.Low, + Category = "Done", + Description = "Analyze stored procedures.", + Progress = 100, + Tags = new List { "Trial preparation" } + }); + + cardDetails.Add(new CardDetails() + { + Title = "Task - 13", + Priority = Priority.Medium, + Index = 20, + Category = "Code Review", + Description = "Analyze grid control.", + Progress = 75, + Tags = new List { "Documentation" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 18, + Title = "Task - 14", + Priority = Priority.Critical, + Category = "Code Review", + Description = "Stored procedure for initial data binding of the grid.", + Progress = 85, + Tags = new List { "Bug" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 23, + Title = "Task - 15", + Priority = Priority.Low, + Category = "Code Review", + Description = "Analyze stored procedures.", + Progress = 88, + Tags = new List { "Analyze" } + }); + + return cardDetails; + } + + #endregion +} + +{% endhighlight %} +{% endtabs %} + +## Model property value updation while drag and drop + +Another way to sort the target column during drag-and-drop is by updating the dropped card’s SortingMappingPath value based on your custom requirements. In the sample, you can access the target column collection using `e.TargetColumn.`Items` in the ``DragEnd` event and apply your own sorting logic. + +The following code example illustrate the model property updation functionality. + +{% tabs %} +{% highlight XAML hl_lines="3" %} + + + + + + + +{% endhighlight %} + +{% highlight C# hl_lines="2" %} + +this.kanban.ItemsSource = new SortingViewModel().Cards; +this.kanban.DragEnd += this.OnCardDragEnd; + +private void OnCardDragEnd(object? sender, KanbanDragEndEventArgs e) +{ + this.ApplySortingWithoutPositionChange(e); +} + +/// +/// Applies sorting without changing the position of the cards. +/// +/// The event args. +private void ApplySortingWithoutPositionChange(KanbanDragEndEventArgs eventArgs) +{ + // Extract and cast items from the target column + var targetColumnItems = eventArgs.TargetColumn.Items is IList items + ? items.Cast().ToList() : new List(); + + //You can customize the order of target column collection... +} + +{% endhighlight %} \ No newline at end of file diff --git a/maui-toc.html b/maui-toc.html index af95fd56a2..afac551f8b 100644 --- a/maui-toc.html +++ b/maui-toc.html @@ -782,8 +782,9 @@
  • Getting Started
  • Migrate from Xamarin.Forms
  • Column
  • -
  • Workflows
  • Cards
  • +
  • Workflows
  • +
  • Sorting
  • Localization
  • Events
  • From b02e659e29e1f9f59f10ca5fc8e709cc571ed8c1 Mon Sep 17 00:00:00 2001 From: AARTHI Date: Mon, 13 Oct 2025 13:26:43 +0530 Subject: [PATCH 2/7] 986416-Added sorting properties to Kanban --- MAUI/Kanban-Board/Sorting.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MAUI/Kanban-Board/Sorting.md b/MAUI/Kanban-Board/Sorting.md index 61e7d4ea80..5f570bd291 100644 --- a/MAUI/Kanban-Board/Sorting.md +++ b/MAUI/Kanban-Board/Sorting.md @@ -28,6 +28,8 @@ The following code example describes the card position changing functionality. @@ -413,7 +415,7 @@ public class SortingViewModel ## Model property value updation while drag and drop -Another way to sort the target column during drag-and-drop is by updating the dropped card’s SortingMappingPath value based on your custom requirements. In the sample, you can access the target column collection using `e.TargetColumn.`Items` in the ``DragEnd` event and apply your own sorting logic. +Another way to sort the target column during drag-and-drop is by updating the dropped card’s SortingMappingPath value based on your custom requirements. In the sample, you can access the target column collection using `e.TargetColumn.Items' in the ``DragEnd` event and apply your own sorting logic. The following code example illustrate the model property updation functionality. @@ -422,6 +424,8 @@ The following code example illustrate the model property updation functionality. From e3fc3baa85ba58aeb995d758cd77a53d186fcb28 Mon Sep 17 00:00:00 2001 From: AARTHI Date: Tue, 14 Oct 2025 10:32:39 +0530 Subject: [PATCH 3/7] 986416-Addressed review changes. --- MAUI/ImageEditor/events.md | 28 --- MAUI/Kanban-Board/Sorting.md | 456 +---------------------------------- 2 files changed, 12 insertions(+), 472 deletions(-) diff --git a/MAUI/ImageEditor/events.md b/MAUI/ImageEditor/events.md index 6afc124a3a..2ed2296b91 100644 --- a/MAUI/ImageEditor/events.md +++ b/MAUI/ImageEditor/events.md @@ -87,31 +87,3 @@ The [`BrowseImage`](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.ImageEdi {% endhighlight %} {% endtabs %} - -## AnnotationsDeserialized event - -The 'AnnotationsDeserialized' event is triggered each time deserialization completes and annotations are applied to the ImageEditor control. This allows users to validate the data, update the UI, or execute custom business logic. - -N> Serialization and deserialization are not applicable for custom annotation views. - -{% tabs %} - -{% highlight xaml tabtitle="MainPage.xaml" %} - - - -{% endhighlight %} - -{% highlight C# tabtitle="MainPage.xaml.cs" %} - - private void OnAnnotationsDeserialized(object? sender, EventArgs e) - { - - // Add anything here, like dispaly alert to show event raised - } - -{% endhighlight %} - -{% endtabs %} diff --git a/MAUI/Kanban-Board/Sorting.md b/MAUI/Kanban-Board/Sorting.md index 5f570bd291..b643a5808c 100644 --- a/MAUI/Kanban-Board/Sorting.md +++ b/MAUI/Kanban-Board/Sorting.md @@ -1,460 +1,28 @@ --- layout: post -title: Sorting in .NET MAUI Kanban control | Syncfusion +title: Sorting in .NET MAUI Kanban control | Syncfusion® description: Learn here all about Sorting support in Syncfusion® .NET MAUI Kanban (SfKanban) control and more. platform: maui -control: Kanban +control: Kanban (SfKanban) documentation: ug keywords: .net maui Kanban sorting, sfKanban sorting in .net maui, .net maui Kanban sorting support. --- -# Sorting in .NET MAUI Kanban (SfKanban) +# Card Item Sorting in .NET MAUI Kanban (SfKanban) -This feature is used to sort the card items on Kanban Columns by following below properties +The Kanban control supports customizable card sorting within columns based on specific data fields such as priority, due date, or status. Sorting can be applied programmatically and updated dynamically at runtime using following properties -* `SortingMappingPath` - This property should correspond to a property name in the KanbanModel or CustomModel. The default value is string.Empty in this case the cards won’t be sorted. -* `SortingOrder` - Defines the order in which cards appear. The default is Ascending. +* `SortingMappingPath` - Used to map the sorting field to a property name in the `KanbanModel` or `CustomModel`. The default value is `string.Empty`, in which case the cards will not be sorted. +* `SortingOrder` - Used to define the direction of cards sorting within each column. * `Ascending` - Cards with lower values appear first. * `Descending` - Cards with higher values appear first. -## Cards position updation while drag and drop +N> This property is applicable only when a valid value is assigned to SortingMappingPath. -In the SfKanban Sorting feature, you can customize how cards are sorted during drag-and-drop actions. When a card is dropped, its position in the target column is updated based on the SortingMappingPath value. +## Sorting Behavior in DragEnd Event -The following code example describes the card position changing functionality. +The `DragEnd` event in the `Kanban` control supports three sorting approaches: -{% tabs %} -{% highlight XAML hl_lines="3" %} - - - - - - - -{% endhighlight %} - -{% highlight C# hl_lines="2" %} - -this.kanban.ItemsSource = new SortingViewModel().Cards; -this.kanban.DragEnd += this.OnCardDragEnd; - -private void OnCardDragEnd(object? sender, KanbanDragEndEventArgs e) -{ - this.kanban.RefreshKanbanColumn(); -} - -{% endhighlight %} - -{% highlight c# tabtitle="CardDetails.cs" %} - -public class CardDetails : INotifyPropertyChanged -{ - #region Fields - - /// - /// The title of the card. - /// - private string? _title; - - /// - /// The description of the card. - /// - private string? _description; - - /// - /// The category of the card. This property is used for column mapping in the Kanban board. - /// - private string? _category; - - /// - /// The list of tags associated with the card. - /// - private List? _tags; - - /// - /// The index of the card. This property is used for sorting the cards within a column. - /// - private int _index; - - /// - /// The priority of the card. This property can be used for additional sorting or filtering. - /// - private Priority? _priority; - - /// - /// The value of the progresbar on each card item. - /// - private double _progress; - - #endregion - - #region Properties - - /// - /// Gets or sets the title of the card. - /// - public string? Title - { - get { return this._title; } - set - { - this._title = value; - this.OnPropertyChanged(nameof(Title)); - } - } - - /// - /// Gets or sets the description of the card. - /// - public string? Description - { - get { return this._description; } - set - { - this._description = value; - this.OnPropertyChanged(nameof(Description)); - } - } - - /// - /// Gets or sets the category of the card. This property is used for column mapping in the Kanban board. - /// - public string? Category - { - get { return this._category; } - set - { - this._category = value; - this.OnPropertyChanged(nameof(Category)); - } - } - - /// - /// Gets or sets the list of tags associated with the card. - /// - public List? Tags - { - get { return this._tags; } - set - { - this._tags = value; - this.OnPropertyChanged(nameof(Tags)); - } - } - - /// - /// Gets or sets the index of the card. This property is used for sorting the cards within a column. - /// - public int Index - { - get { return this._index; } - set - { - this._index = value; - this.OnPropertyChanged(nameof(Index)); - } - } - - /// - /// Gets or sets the priority of the card. This property can be used for additional sorting or filtering. - /// - public Priority? Priority - { - get { return this._priority; } - set - { - this._priority = value; - this.OnPropertyChanged(nameof(Priority)); - } - } - - /// - /// Gets or sets the ProgressBar value associated with the card. - /// - public double Progress - { - get { return this._progress; } - set - { - if (this._progress != value) - { - this._progress = value; - this.OnPropertyChanged(nameof(Progress)); - } - } - } - - #endregion - - #region Event - - /// - /// Occurs when a property value changes. - /// - public event PropertyChangedEventHandler? PropertyChanged; - - #endregion - - #region Methods - - /// - /// Invokes the event when the value of a property has changed. - /// - /// The name of the property that has changed. - private void OnPropertyChanged(string propertyName) - { - this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - #endregion -} - -{% endhighlight %} - -{% highlight c# tabtitle="SortingViewModel.cs" %} - -public class SortingViewModel -{ - #region Constructor - - /// - /// Initializes a new instance of the class. - /// - public SortingViewModel() - { - this.Cards = this.GetCardDetails(); - } - - #endregion - - #region Properties - - /// - /// Gets or sets the collection of objects representing cards in various stages. - /// - public ObservableCollection Cards { get; set; } - - #endregion - - #region Private method - - /// - /// Method to retrieve a predefined collection of Kanban cards with sorting metadata. - /// - /// The card collection. - private ObservableCollection GetCardDetails() - { - var cardDetails = new ObservableCollection(); - cardDetails.Add(new CardDetails() - { - Index = 5, - Priority = Priority.Medium, - Title = "Task - 1", - Category = "Open", - Description = "Fix the issue reported in the Edge browser.", - Progress = 0, - Tags = new List { "Analyze", "Bug" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 2, - Title = "Task - 3", - Priority = Priority.Low, - Category = "Open", - Description = "Analyze the new requirements gathered from the customer.", - Progress = 0, - Tags = new List { "Trial preparation" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 3, - Title = "Task - 4", - Priority = Priority.Critical, - Category = "Open", - Description = "Arrange a web meeting with the customer to get new requirements.", - Progress = 0, - Tags = new List { "Litigation support" } - }); - - cardDetails.Add(new CardDetails() - { - Title = "Task - 2", - Priority = Priority.High, - Index = 4, - Category = "In Progress", - Description = "Test the application in the Edge browser.", - Progress = 40, - Tags = new List { "Documentation" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 1, - Title = "Task - 5", - Priority = Priority.Medium, - Category = "Open", - Description = "Enhance editing functionality.", - Progress = 0, - Tags = new List { "Analyze" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 7, - Title = "Task - 6", - Priority = Priority.Low, - Category = "Open", - Description = "Arrange web meeting with the customer to show editing demo.", - Progress = 0, - Tags = new List { "Bug" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 6, - Title = "Task - 8", - Priority = Priority.Medium, - Category = "Done", - Description = "Improve application performance.", - Progress = 100, - Tags = new List { "Litigation support" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 10, - Title = "Task - 7", - Priority = Priority.Critical, - Category = "In Progress", - Description = "Fix cannot open user's default database SQL error.", - Progress = 50, - Tags = new List { "Trial preparation" } - }); - - cardDetails.Add(new CardDetails() - { - Title = "Task - 9", - Priority = Priority.Medium, - Index = 8, - Category = "In Progress", - Description = "Improve the performance of the editing functionality.", - Progress = 55, - Tags = new List { "Bug" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 9, - Title = "Task - 10", - Priority = Priority.High, - Category = "Done", - Description = "Analyze grid control.", - Progress = 100, - Tags = new List { "Documentation" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 15, - Title = "Task - 12", - Priority = Priority.Low, - Category = "Done", - Description = "Analyze stored procedures.", - Progress = 100, - Tags = new List { "Trial preparation" } - }); - - cardDetails.Add(new CardDetails() - { - Title = "Task - 13", - Priority = Priority.Medium, - Index = 20, - Category = "Code Review", - Description = "Analyze grid control.", - Progress = 75, - Tags = new List { "Documentation" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 18, - Title = "Task - 14", - Priority = Priority.Critical, - Category = "Code Review", - Description = "Stored procedure for initial data binding of the grid.", - Progress = 85, - Tags = new List { "Bug" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 23, - Title = "Task - 15", - Priority = Priority.Low, - Category = "Code Review", - Description = "Analyze stored procedures.", - Progress = 88, - Tags = new List { "Analyze" } - }); - - return cardDetails; - } - - #endregion -} - -{% endhighlight %} -{% endtabs %} - -## Model property value updation while drag and drop - -Another way to sort the target column during drag-and-drop is by updating the dropped card’s SortingMappingPath value based on your custom requirements. In the sample, you can access the target column collection using `e.TargetColumn.Items' in the ``DragEnd` event and apply your own sorting logic. - -The following code example illustrate the model property updation functionality. - -{% tabs %} -{% highlight XAML hl_lines="3" %} - - - - - - - -{% endhighlight %} - -{% highlight C# hl_lines="2" %} - -this.kanban.ItemsSource = new SortingViewModel().Cards; -this.kanban.DragEnd += this.OnCardDragEnd; - -private void OnCardDragEnd(object? sender, KanbanDragEndEventArgs e) -{ - this.ApplySortingWithoutPositionChange(e); -} - -/// -/// Applies sorting without changing the position of the cards. -/// -/// The event args. -private void ApplySortingWithoutPositionChange(KanbanDragEndEventArgs eventArgs) -{ - // Extract and cast items from the target column - var targetColumnItems = eventArgs.TargetColumn.Items is IList items - ? items.Cast().ToList() : new List(); - - //You can customize the order of target column collection... -} - -{% endhighlight %} \ No newline at end of file +* **Automatic Sorting**: Call RefreshKanbanColumn() to sort the target column based on predefined sorting properties after a card is dropped. +* **Custom Sorting**: Use e.TargetColumn.Items to access and sort the cards manually using your own logic. +* **No Sorting**: If no sorting logic is applied in the DragEnd event, the dropped card remains in its new position without reordering the column. \ No newline at end of file From 159082c3b36a727124f22bfae7a3dd46980a8fb7 Mon Sep 17 00:00:00 2001 From: AARTHI Date: Tue, 14 Oct 2025 16:17:51 +0530 Subject: [PATCH 4/7] 986416-Modified Sorting feature content. --- MAUI/Kanban-Board/Sorting.md | 677 ++++++++++++++++++++++++++++++++++- 1 file changed, 671 insertions(+), 6 deletions(-) diff --git a/MAUI/Kanban-Board/Sorting.md b/MAUI/Kanban-Board/Sorting.md index b643a5808c..0120846c2a 100644 --- a/MAUI/Kanban-Board/Sorting.md +++ b/MAUI/Kanban-Board/Sorting.md @@ -1,7 +1,7 @@ --- layout: post title: Sorting in .NET MAUI Kanban control | Syncfusion® -description: Learn here all about Sorting support in Syncfusion® .NET MAUI Kanban (SfKanban) control and more. +description: Learn here all about Sorting support in Syncfusion® .NET MAUI Kanban(SfKanban) control and more. platform: maui control: Kanban (SfKanban) documentation: ug @@ -10,19 +10,684 @@ keywords: .net maui Kanban sorting, sfKanban sorting in .net maui, .net maui Kan # Card Item Sorting in .NET MAUI Kanban (SfKanban) -The Kanban control supports customizable card sorting within columns based on specific data fields such as priority, due date, or status. Sorting can be applied programmatically and updated dynamically at runtime using following properties +The Kanban control supports customizable card sorting within columns based on specific data fields such as `priority`, `due date`, or `status`. Sorting can be applied programmatically and updated dynamically at runtime using following properties. * `SortingMappingPath` - Used to map the sorting field to a property name in the `KanbanModel` or `CustomModel`. The default value is `string.Empty`, in which case the cards will not be sorted. * `SortingOrder` - Used to define the direction of cards sorting within each column. * `Ascending` - Cards with lower values appear first. * `Descending` - Cards with higher values appear first. -N> This property is applicable only when a valid value is assigned to SortingMappingPath. +N> This property is applicable only when a valid value is assigned to `SortingMappingPath`. ## Sorting Behavior in DragEnd Event The `DragEnd` event in the `Kanban` control supports three sorting approaches: -* **Automatic Sorting**: Call RefreshKanbanColumn() to sort the target column based on predefined sorting properties after a card is dropped. -* **Custom Sorting**: Use e.TargetColumn.Items to access and sort the cards manually using your own logic. -* **No Sorting**: If no sorting logic is applied in the DragEnd event, the dropped card remains in its new position without reordering the column. \ No newline at end of file + * Custom + * Index + * ItemsSource Order + +### Custom + +The SortBy Custom approach must require SortingMappingPath value. In this behavior, cards are sorted and loaded based on the SortingMappingPath value and also cards are dropped based on the SortingMappingPath value to maintain consistent sorting behavior. + +The following code example describes the card position changing functionality. + +{% tabs %} +{% highlight XAML hl_lines="3" %} + + + + + + + +{% endhighlight %} +{% highlight C# %} + +this.kanban.ItemsSource = new SortingViewModel().Cards; +this.kanban.DragEnd += this.OnCardDragEnd; + +private void OnCardDragEnd(object? sender, KanbanDragEndEventArgs e) +{ + this.kanban.RefreshKanbanColumn(); +} + +{% endhighlight %} + +{% highlight c# tabtitle="CardDetails.cs" %} + +public class CardDetails : INotifyPropertyChanged +{ + #region Fields + + /// + /// The title of the card. + /// + private string? _title; + + /// + /// The description of the card. + /// + private string? _description; + + /// + /// The category of the card. This property is used for column mapping in the Kanban board. + /// + private string? _category; + + /// + /// The list of tags associated with the card. + /// + private List? _tags; + + /// + /// The index of the card. This property is used for sorting the cards within a column. + /// + private int _index; + + /// + /// The priority of the card. This property can be used for additional sorting or filtering. + /// + private Priority? _priority; + + /// + /// The value of the progresbar on each card item. + /// + private double _progress; + + #endregion + + #region Properties + + /// + /// Gets or sets the title of the card. + /// + public string? Title + { + get { return this._title; } + set + { + this._title = value; + this.OnPropertyChanged(nameof(Title)); + } + } + + /// + /// Gets or sets the description of the card. + /// + public string? Description + { + get { return this._description; } + set + { + this._description = value; + this.OnPropertyChanged(nameof(Description)); + } + } + + /// + /// Gets or sets the category of the card. This property is used for column mapping in the Kanban board. + /// + public string? Category + { + get { return this._category; } + set + { + this._category = value; + this.OnPropertyChanged(nameof(Category)); + } + } + + /// + /// Gets or sets the list of tags associated with the card. + /// + public List? Tags + { + get { return this._tags; } + set + { + this._tags = value; + this.OnPropertyChanged(nameof(Tags)); + } + } + + /// + /// Gets or sets the index of the card. This property is used for sorting the cards within a column. + /// + public int Index + { + get { return this._index; } + set + { + this._index = value; + this.OnPropertyChanged(nameof(Index)); + } + } + + /// + /// Gets or sets the priority of the card. This property can be used for additional sorting or filtering. + /// + public Priority? Priority + { + get { return this._priority; } + set + { + this._priority = value; + this.OnPropertyChanged(nameof(Priority)); + } + } + + /// + /// Gets or sets the ProgressBar value associated with the card. + /// + public double Progress + { + get { return this._progress; } + set + { + if (this._progress != value) + { + this._progress = value; + this.OnPropertyChanged(nameof(Progress)); + } + } + } + + #endregion + + #region Event + + /// + /// Occurs when a property value changes. + /// + public event PropertyChangedEventHandler? PropertyChanged; + + #endregion + + #region Methods + + /// + /// Invokes the event when the value of a property has changed. + /// + /// The name of the property that has changed. + private void OnPropertyChanged(string propertyName) + { + this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + #endregion +} + +{% endhighlight %} + +{% highlight c# tabtitle="SortingViewModel.cs" %} + +public class SortingViewModel +{ + #region Constructor + + /// + /// Initializes a new instance of the class. + /// + public SortingViewModel() + { + this.Cards = this.GetCardDetails(); + } + + #endregion + + #region Properties + + /// + /// Gets or sets the collection of objects representing cards in various stages. + /// + public ObservableCollection Cards { get; set; } + + #endregion + + #region Private method + + /// + /// Method to retrieve a predefined collection of Kanban cards with sorting metadata. + /// + /// The card collection. + private ObservableCollection GetCardDetails() + { + var cardDetails = new ObservableCollection(); + cardDetails.Add(new CardDetails() + { + Index = 5, + Priority = Priority.Medium, + Title = "Task - 1", + Category = "Open", + Description = "Fix the issue reported in the Edge browser.", + Progress = 0, + Tags = new List { "Analyze", "Bug" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 2, + Title = "Task - 3", + Priority = Priority.Low, + Category = "Open", + Description = "Analyze the new requirements gathered from the customer.", + Progress = 0, + Tags = new List { "Trial preparation" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 3, + Title = "Task - 4", + Priority = Priority.Critical, + Category = "Open", + Description = "Arrange a web meeting with the customer to get new requirements.", + Progress = 0, + Tags = new List { "Litigation support" } + }); + + cardDetails.Add(new CardDetails() + { + Title = "Task - 2", + Priority = Priority.High, + Index = 4, + Category = "In Progress", + Description = "Test the application in the Edge browser.", + Progress = 40, + Tags = new List { "Documentation" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 1, + Title = "Task - 5", + Priority = Priority.Medium, + Category = "Open", + Description = "Enhance editing functionality.", + Progress = 0, + Tags = new List { "Analyze" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 7, + Title = "Task - 6", + Priority = Priority.Low, + Category = "Open", + Description = "Arrange web meeting with the customer to show editing demo.", + Progress = 0, + Tags = new List { "Bug" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 6, + Title = "Task - 8", + Priority = Priority.Medium, + Category = "Done", + Description = "Improve application performance.", + Progress = 100, + Tags = new List { "Litigation support" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 10, + Title = "Task - 7", + Priority = Priority.Critical, + Category = "In Progress", + Description = "Fix cannot open user's default database SQL error.", + Progress = 50, + Tags = new List { "Trial preparation" } + }); + + cardDetails.Add(new CardDetails() + { + Title = "Task - 9", + Priority = Priority.Medium, + Index = 8, + Category = "In Progress", + Description = "Improve the performance of the editing functionality.", + Progress = 55, + Tags = new List { "Bug" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 9, + Title = "Task - 10", + Priority = Priority.High, + Category = "Done", + Description = "Analyze grid control.", + Progress = 100, + Tags = new List { "Documentation" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 15, + Title = "Task - 12", + Priority = Priority.Low, + Category = "Done", + Description = "Analyze stored procedures.", + Progress = 100, + Tags = new List { "Trial preparation" } + }); + + cardDetails.Add(new CardDetails() + { + Title = "Task - 13", + Priority = Priority.Medium, + Index = 20, + Category = "Code Review", + Description = "Analyze grid control.", + Progress = 75, + Tags = new List { "Documentation" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 18, + Title = "Task - 14", + Priority = Priority.Critical, + Category = "Code Review", + Description = "Stored procedure for initial data binding of the grid.", + Progress = 85, + Tags = new List { "Bug" } + }); + + cardDetails.Add(new CardDetails() + { + Index = 23, + Title = "Task - 15", + Priority = Priority.Low, + Category = "Code Review", + Description = "Analyze stored procedures.", + Progress = 88, + Tags = new List { "Analyze" } + }); + + return cardDetails; + } + + #endregion +} + +{% endhighlight %} +{% endtabs %} + +### Index + +SortBy Index approach also depends SortingMappingPath value. This approach allows the users to drop the cards in the Kanban column where the placeholder view is created exactly. It is also helpful to render the cards based on the SortingMappingPath value. + +N> The SortingMappingPath property value must be in number format. + +The following cases will dynamically change their SortingMappingPath value when dropping the cards. + +* If the column has one card and dropped a card to the last position or previous/next cards that do not have continuous order, then the dropped card SortingMappingPath value will be changed based on their previous card value. + +* If the column has one card and dropped a card on the previous position, then it will compare both the values, and the dropped card field value will be changed if the cards have continuous order otherwise values will not be changed. + +* When the previous and next cards do not have continuous order, the dropped card SortingMappingPath value will be changed based on the previous card value. + +* When the previous and next cards have continuous order value, then the SortingMappingPath value of the dropped card and the cards followed by the dropped card will be changed based on the previous card value with continuous order. + +For Example, +Continuous Order - +Consider, Column A has Card A with priority value 1, Card B with priority value 2, and Card C with priority value 3. +and Column B has Card D with priority value 5, then the dropped Card D will be placed between Card A and Card B. Now, the Cards D, B, and C will be dynamically changed to the priority values as 2, 3, and 4 respectively. + +The following code example illustrate the index updation functionality. + +{% tabs %} +{% highlight XAML hl_lines="3" %} + + + + + + + +{% endhighlight %} + +{% highlight C# %} + +this.kanban.ItemsSource = new SortingViewModel().Cards; +this.kanban.DragEnd += this.OnCardDragEnd; + +private void OnCardDragEnd(object? sender, KanbanDragEndEventArgs e) +{ + this.ApplySortingWithoutPositionChange(e); +} + +/// +/// Applies sorting without changing the position of the cards. +/// +private void ApplySortingWithoutPositionChange(KanbanDragEndEventArgs eventArgs) +{ + if (this.kanban == null || eventArgs.Data == null || eventArgs.TargetColumn?.Items == null || eventArgs.SourceColumn == null || (eventArgs.SourceColumn == eventArgs.TargetColumn && eventArgs.SourceIndex == eventArgs.TargetIndex)) + { + return; + } + + // Retrieve sorting configuration + var sortMappingPath = kanban.SortingMappingPath; + var sortingOrder = kanban.SortingOrder; + + // Extract and cast items from the target column + var targetColumnItems = eventArgs.TargetColumn.Items is IList items + ? items.Cast().ToList() : new List(); + + // Proceed only if sorting path is defined + if (string.IsNullOrEmpty(sortMappingPath)) + { + return; + } + + // Sort items based on the sorting order + if (targetColumnItems.Count > 0) + { + Func keySelector = item => this.GetPropertyInfo(item.GetType(), sortMappingPath); + + targetColumnItems = sortingOrder == KanbanSortingOrder.Ascending + ? targetColumnItems.OrderBy(item => keySelector(item) ?? 0).ToList() + : targetColumnItems.OrderByDescending(item => keySelector(item) ?? 0).ToList(); + } + + // Determine the index to insert the dragged card. + int currentCardIndex = eventArgs.TargetIndex; + if (currentCardIndex >= 0 && currentCardIndex <= targetColumnItems.Count) + { + targetColumnItems.Insert(currentCardIndex, eventArgs.Data); + } + else + { + targetColumnItems.Add(eventArgs.Data); + currentCardIndex = targetColumnItems.Count - 1; + } + + // Update index property of all items using smart positioning logic + this.ApplySmartIndexUpdate(targetColumnItems, sortingOrder, currentCardIndex); +} + +/// +/// Method to get the property info for the specified property. +/// +private PropertyInfo? GetPropertyInfo(Type type, string key) +{ + return this.GetPropertyInfoCustomType(type, key); +} + +/// +/// Method to get the property info for the specified property from the given type. +/// +private PropertyInfo? GetPropertyInfoCustomType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type, string key) +{ + return type.GetProperty(key); +} + +/// +/// Updates index property with smart positioning based on sorting order. +/// +private void ApplySmartIndexUpdate(List items, KanbanSortingOrder sortingOrder, int currentCardIndex) +{ + if (items == null || items.Count == 0) + { + return; + } + + if (sortingOrder == KanbanSortingOrder.Ascending) + { + this.HandleAscendingIndexSorting(items, currentCardIndex); + return; + } + + this.HandleDescendingIndexSorting(items, currentCardIndex); +} + +/// +/// Method to handle ascending index sorting with smart positioning. +/// +private void HandleAscendingIndexSorting(List items, int currentCardIndex) +{ + int afterCardIndex = -1; + int lastItemIndex = -1; + + // Get the index of the card after the insertion point + if (currentCardIndex < items.Count - 1) + { + var afterCard = items[currentCardIndex + 1]; + afterCardIndex = GetCardIndex(afterCard) ?? -1; + } + + for (int i = 0; i < items.Count; i++) + { + var item = items[i]; + if (item == null) + { + continue; + } + + PropertyInfo? propertyInfo = this.GetPropertyInfo(item.GetType(), "Index"); + if (propertyInfo == null) + { + continue; + } + + int itemIndex = Convert.ToInt32(propertyInfo.GetValue(item) ?? 0); + bool isFirstItem = i == 0; + if (isFirstItem) + { + // If the inserted card is at the beginning, assign a smart index + if (currentCardIndex == 0) + { + lastItemIndex = afterCardIndex > 1 ? afterCardIndex - 1 : 1; + propertyInfo.SetValue(item, lastItemIndex); + } + else + { + lastItemIndex = itemIndex; + } + } + else + { + // Increment index for subsequent items + lastItemIndex++; + propertyInfo.SetValue(item, lastItemIndex); + } + } +} + +/// +/// Method to handle descending index sorting with smart positioning. +/// +private void HandleDescendingIndexSorting(List items, int currentCardIndex) +{ + int beforeCardIndex = -1; + int lastItemIndex = -1; + + // Get the index of the card before the insertion point + if (currentCardIndex > 0 && currentCardIndex < items.Count) + { + var cardBefore = items[currentCardIndex - 1]; + beforeCardIndex = GetCardIndex(cardBefore) ?? -1; + } + + for (int i = items.Count - 1; i >= 0; i--) + { + var item = items[i]; + if (item == null) + { + continue; + } + + PropertyInfo? propertyInfo = this.GetPropertyInfo(item.GetType(), "Index"); + if (propertyInfo == null) + { + continue; + } + + int itemIndex = Convert.ToInt32(propertyInfo.GetValue(item) ?? 0); + bool isLastItem = i == items.Count - 1; + if (isLastItem) + { + // If the inserted card is at the end, assign a smart index + if (currentCardIndex == items.Count - 1) + { + lastItemIndex = beforeCardIndex > 1 ? beforeCardIndex - 1 : 1; + propertyInfo.SetValue(item, lastItemIndex); + } + else + { + lastItemIndex = itemIndex; + } + } + else + { + lastItemIndex++; + propertyInfo.SetValue(item, lastItemIndex); + } + } +} + +/// +/// Method to get the index property value from a card object. +/// +private int? GetCardIndex(object cardDetails) +{ + if (cardDetails == null) + { + return null; + } + + PropertyInfo? propertyInfo = this.GetPropertyInfo(cardDetails.GetType(), "Index"); + if (propertyInfo == null) + { + return null; + } + + var indexValue = propertyInfo.GetValue(cardDetails); + if (indexValue != null) + { + return Convert.ToInt32(indexValue); + } + + return null; +} + +{% endhighlight %} +{% endtabs %} + +### ItemsSource Order + +The SortBy ItemsSource order approach does not require any SortingMappingPath value. In this behavior, cards are loaded based on the ItemsSource order, and also cards are dropped where the placeholder view is created exactly. \ No newline at end of file From 70d0156bafbc53905e2d23cd6d6b8bcb6f2e8a59 Mon Sep 17 00:00:00 2001 From: AARTHI Date: Wed, 15 Oct 2025 19:27:40 +0530 Subject: [PATCH 5/7] 986416-Added SfKanban sorting UG content --- MAUI/Kanban-Board/Sorting.md | 699 ++++++----------------------------- 1 file changed, 106 insertions(+), 593 deletions(-) diff --git a/MAUI/Kanban-Board/Sorting.md b/MAUI/Kanban-Board/Sorting.md index 0120846c2a..837f24f7a3 100644 --- a/MAUI/Kanban-Board/Sorting.md +++ b/MAUI/Kanban-Board/Sorting.md @@ -8,46 +8,61 @@ documentation: ug keywords: .net maui Kanban sorting, sfKanban sorting in .net maui, .net maui Kanban sorting support. --- -# Card Item Sorting in .NET MAUI Kanban (SfKanban) +# Card Item Sorting in .NET MAUI Kanban(SfKanban) -The Kanban control supports customizable card sorting within columns based on specific data fields such as `priority`, `due date`, or `status`. Sorting can be applied programmatically and updated dynamically at runtime using following properties. +The Kanban control supports customizable card sorting within columns based on specific data fields such as `Priority`, `DueDate`, or `Status`. Sorting can be configured programmatically and updated dynamically at runtime using the following properties: * `SortingMappingPath` - Used to map the sorting field to a property name in the `KanbanModel` or `CustomModel`. The default value is `string.Empty`, in which case the cards will not be sorted. * `SortingOrder` - Used to define the direction of cards sorting within each column. * `Ascending` - Cards with lower values appear first. * `Descending` - Cards with higher values appear first. -N> This property is applicable only when a valid value is assigned to `SortingMappingPath`. +N> The `SortingOrder` property is applicable only when a valid value is assigned to `SortingMappingPath`. -## Sorting Behavior in DragEnd Event +## Customize card order with sorting configuration -The `DragEnd` event in the `Kanban` control supports three sorting approaches: +Sorting in the Kanban control can be implemented using the following approaches. * Custom * Index - * ItemsSource Order -### Custom +### Custom Field Sorting -The SortBy Custom approach must require SortingMappingPath value. In this behavior, cards are sorted and loaded based on the SortingMappingPath value and also cards are dropped based on the SortingMappingPath value to maintain consistent sorting behavior. +To enable custom sorting behavior, a valid property name from the `ItemsSource` must be mapped using the `SortingMappingPath` property. This mapping ensures that cards are loaded and repositioned based on the corresponding property value, allowing consistent sorting during both initialization and drag-and-drop operations. -The following code example describes the card position changing functionality. +This example demonstrates how card positions are updated based on sorting configurations and property mappings. {% tabs %} -{% highlight XAML hl_lines="3" %} +{% highlight XAML hl_lines="3 5" %} - + ItemsSource="{Binding Cards}" + ColumnMappingPath="Category"> + + + + + + + + + + + + + {% endhighlight %} -{% highlight C# %} +{% highlight C# hl_lines="2 6" %} this.kanban.ItemsSource = new SortingViewModel().Cards; this.kanban.DragEnd += this.OnCardDragEnd; @@ -58,409 +73,86 @@ private void OnCardDragEnd(object? sender, KanbanDragEndEventArgs e) } {% endhighlight %} - {% highlight c# tabtitle="CardDetails.cs" %} -public class CardDetails : INotifyPropertyChanged +public class CardDetails { - #region Fields - - /// - /// The title of the card. - /// - private string? _title; - - /// - /// The description of the card. - /// - private string? _description; - - /// - /// The category of the card. This property is used for column mapping in the Kanban board. - /// - private string? _category; - - /// - /// The list of tags associated with the card. - /// - private List? _tags; - - /// - /// The index of the card. This property is used for sorting the cards within a column. - /// - private int _index; - - /// - /// The priority of the card. This property can be used for additional sorting or filtering. - /// - private Priority? _priority; - - /// - /// The value of the progresbar on each card item. - /// - private double _progress; - - #endregion - - #region Properties - - /// - /// Gets or sets the title of the card. - /// - public string? Title - { - get { return this._title; } - set - { - this._title = value; - this.OnPropertyChanged(nameof(Title)); - } - } - - /// - /// Gets or sets the description of the card. - /// - public string? Description - { - get { return this._description; } - set - { - this._description = value; - this.OnPropertyChanged(nameof(Description)); - } - } - - /// - /// Gets or sets the category of the card. This property is used for column mapping in the Kanban board. - /// - public string? Category - { - get { return this._category; } - set - { - this._category = value; - this.OnPropertyChanged(nameof(Category)); - } - } - - /// - /// Gets or sets the list of tags associated with the card. - /// - public List? Tags - { - get { return this._tags; } - set - { - this._tags = value; - this.OnPropertyChanged(nameof(Tags)); - } - } - - /// - /// Gets or sets the index of the card. This property is used for sorting the cards within a column. - /// - public int Index - { - get { return this._index; } - set - { - this._index = value; - this.OnPropertyChanged(nameof(Index)); - } - } - - /// - /// Gets or sets the priority of the card. This property can be used for additional sorting or filtering. - /// - public Priority? Priority - { - get { return this._priority; } - set - { - this._priority = value; - this.OnPropertyChanged(nameof(Priority)); - } - } - - /// - /// Gets or sets the ProgressBar value associated with the card. - /// - public double Progress - { - get { return this._progress; } - set - { - if (this._progress != value) - { - this._progress = value; - this.OnPropertyChanged(nameof(Progress)); - } - } - } - - #endregion - - #region Event - - /// - /// Occurs when a property value changes. - /// - public event PropertyChangedEventHandler? PropertyChanged; - - #endregion - - #region Methods - - /// - /// Invokes the event when the value of a property has changed. - /// - /// The name of the property that has changed. - private void OnPropertyChanged(string propertyName) - { - this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - #endregion + public string? Title { get; set; } + public string? Description { get; set; } + public string? Priority { get; set; } + public string? Category { get; set; } } {% endhighlight %} - {% highlight c# tabtitle="SortingViewModel.cs" %} public class SortingViewModel { - #region Constructor - - /// - /// Initializes a new instance of the class. - /// public SortingViewModel() { - this.Cards = this.GetCardDetails(); - } - - #endregion - - #region Properties - - /// - /// Gets or sets the collection of objects representing cards in various stages. - /// - public ObservableCollection Cards { get; set; } - - #endregion - - #region Private method - - /// - /// Method to retrieve a predefined collection of Kanban cards with sorting metadata. - /// - /// The card collection. - private ObservableCollection GetCardDetails() - { - var cardDetails = new ObservableCollection(); - cardDetails.Add(new CardDetails() - { - Index = 5, - Priority = Priority.Medium, - Title = "Task - 1", - Category = "Open", - Description = "Fix the issue reported in the Edge browser.", - Progress = 0, - Tags = new List { "Analyze", "Bug" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 2, - Title = "Task - 3", - Priority = Priority.Low, - Category = "Open", - Description = "Analyze the new requirements gathered from the customer.", - Progress = 0, - Tags = new List { "Trial preparation" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 3, - Title = "Task - 4", - Priority = Priority.Critical, - Category = "Open", - Description = "Arrange a web meeting with the customer to get new requirements.", - Progress = 0, - Tags = new List { "Litigation support" } - }); - - cardDetails.Add(new CardDetails() + this.Cards = new ObservableCollection() { - Title = "Task - 2", - Priority = Priority.High, - Index = 4, - Category = "In Progress", - Description = "Test the application in the Edge browser.", - Progress = 40, - Tags = new List { "Documentation" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 1, - Title = "Task - 5", - Priority = Priority.Medium, - Category = "Open", - Description = "Enhance editing functionality.", - Progress = 0, - Tags = new List { "Analyze" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 7, - Title = "Task - 6", - Priority = Priority.Low, - Category = "Open", - Description = "Arrange web meeting with the customer to show editing demo.", - Progress = 0, - Tags = new List { "Bug" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 6, - Title = "Task - 8", - Priority = Priority.Medium, - Category = "Done", - Description = "Improve application performance.", - Progress = 100, - Tags = new List { "Litigation support" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 10, - Title = "Task - 7", - Priority = Priority.Critical, - Category = "In Progress", - Description = "Fix cannot open user's default database SQL error.", - Progress = 50, - Tags = new List { "Trial preparation" } - }); - - cardDetails.Add(new CardDetails() - { - Title = "Task - 9", - Priority = Priority.Medium, - Index = 8, - Category = "In Progress", - Description = "Improve the performance of the editing functionality.", - Progress = 55, - Tags = new List { "Bug" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 9, - Title = "Task - 10", - Priority = Priority.High, - Category = "Done", - Description = "Analyze grid control.", - Progress = 100, - Tags = new List { "Documentation" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 15, - Title = "Task - 12", - Priority = Priority.Low, - Category = "Done", - Description = "Analyze stored procedures.", - Progress = 100, - Tags = new List { "Trial preparation" } - }); - - cardDetails.Add(new CardDetails() - { - Title = "Task - 13", - Priority = Priority.Medium, - Index = 20, - Category = "Code Review", - Description = "Analyze grid control.", - Progress = 75, - Tags = new List { "Documentation" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 18, - Title = "Task - 14", - Priority = Priority.Critical, - Category = "Code Review", - Description = "Stored procedure for initial data binding of the grid.", - Progress = 85, - Tags = new List { "Bug" } - }); - - cardDetails.Add(new CardDetails() - { - Index = 23, - Title = "Task - 15", - Priority = Priority.Low, - Category = "Code Review", - Description = "Analyze stored procedures.", - Progress = 88, - Tags = new List { "Analyze" } - }); - - return cardDetails; + new CardDetails() { Title = "Task - 1", Priority = "Medium", Category = "Open", Description = "Fix the issue reported in the Edge browser." }, + new CardDetails() { Title = "Task - 3", Priority = "Low", Category = "In Progress", Description = "Analyze the new requirements gathered from the customer." }, + new CardDetails() { Title = "Task - 4", Priority = "Critical", Category = "Open", Description = "Arrange a web meeting with the customer to get new requirements." }, + new CardDetails() { Title = "Task - 2", Priority = "High", Category = "In Progress", Description = "Test the application in the Edge browser." }, + new CardDetails() { Title = "Task - 5", Priority = "Medium", Category = "Done", Description = "Enhance editing functionality." }, + new CardDetails() { Title = "Task - 8", Priority = "Medium", Category = "In Progress", Description = "Improve application performance." }, + new CardDetails() { Title = "Task - 9", Priority = "Medium", Category = "Done", Description = "Improve the performance of the editing functionality." }, + new CardDetails() { Title = "Task - 10", Priority = "High", Category = "Open", Description = "Analyze grid control." }, + new CardDetails() { Title = "Task - 12", Priority = "Low", Category = "Done", Description = "Analyze stored procedures." } + }; } - #endregion + public ObservableCollection Cards { get; set; } } +N> + * To apply sorting after a drop operation, handle the `DragEnd` event and explicitly call the `RefreshKanbanColumn` method. This ensures the column updates to reflect the new card order based on the defined sorting logic. + * When using a custom data model, the default card UI is not applicable. To render the card content, you must define a custom `DataTemplate` using the `CardTemplate` property. + {% endhighlight %} {% endtabs %} -### Index +### Index-Based Sorting -SortBy Index approach also depends SortingMappingPath value. This approach allows the users to drop the cards in the Kanban column where the placeholder view is created exactly. It is also helpful to render the cards based on the SortingMappingPath value. +The index-based approach in the Kanban control allows cards to be dropped at precise positions within a column. Upon dropping, the card's index is updated based on the index of the previous card. Additionally, the index of the next card is incremented relative to the drop position to maintain continuous ordering. -N> The SortingMappingPath property value must be in number format. +N> The `SortingMappingPath` property must be mapped to a valid numeric property name from the `ItemsSource` to enable index-based sorting updates. -The following cases will dynamically change their SortingMappingPath value when dropping the cards. - -* If the column has one card and dropped a card to the last position or previous/next cards that do not have continuous order, then the dropped card SortingMappingPath value will be changed based on their previous card value. - -* If the column has one card and dropped a card on the previous position, then it will compare both the values, and the dropped card field value will be changed if the cards have continuous order otherwise values will not be changed. - -* When the previous and next cards do not have continuous order, the dropped card SortingMappingPath value will be changed based on the previous card value. - -* When the previous and next cards have continuous order value, then the SortingMappingPath value of the dropped card and the cards followed by the dropped card will be changed based on the previous card value with continuous order. - -For Example, -Continuous Order - -Consider, Column A has Card A with priority value 1, Card B with priority value 2, and Card C with priority value 3. -and Column B has Card D with priority value 5, then the dropped Card D will be placed between Card A and Card B. Now, the Cards D, B, and C will be dynamically changed to the priority values as 2, 3, and 4 respectively. - -The following code example illustrate the index updation functionality. +The following code example illustrates how cards numeric property updated using the index-based sorting approach. {% tabs %} -{% highlight XAML hl_lines="3" %} +{% highlight XAML hl_lines="2 3" %} - + ItemsSource="{Binding Cards}" + ColumnMappingPath="Category"> + + + + + + + + + + + + + {% endhighlight %} - -{% highlight C# %} +{% highlight C# hl_lines="2 6 7" %} this.kanban.ItemsSource = new SortingViewModel().Cards; this.kanban.DragEnd += this.OnCardDragEnd; @@ -468,226 +160,47 @@ this.kanban.DragEnd += this.OnCardDragEnd; private void OnCardDragEnd(object? sender, KanbanDragEndEventArgs e) { this.ApplySortingWithoutPositionChange(e); + this.kanban.RefreshKanbanColumn(); } -/// -/// Applies sorting without changing the position of the cards. -/// -private void ApplySortingWithoutPositionChange(KanbanDragEndEventArgs eventArgs) -{ - if (this.kanban == null || eventArgs.Data == null || eventArgs.TargetColumn?.Items == null || eventArgs.SourceColumn == null || (eventArgs.SourceColumn == eventArgs.TargetColumn && eventArgs.SourceIndex == eventArgs.TargetIndex)) - { - return; - } - - // Retrieve sorting configuration - var sortMappingPath = kanban.SortingMappingPath; - var sortingOrder = kanban.SortingOrder; - - // Extract and cast items from the target column - var targetColumnItems = eventArgs.TargetColumn.Items is IList items - ? items.Cast().ToList() : new List(); - - // Proceed only if sorting path is defined - if (string.IsNullOrEmpty(sortMappingPath)) - { - return; - } - - // Sort items based on the sorting order - if (targetColumnItems.Count > 0) - { - Func keySelector = item => this.GetPropertyInfo(item.GetType(), sortMappingPath); - - targetColumnItems = sortingOrder == KanbanSortingOrder.Ascending - ? targetColumnItems.OrderBy(item => keySelector(item) ?? 0).ToList() - : targetColumnItems.OrderByDescending(item => keySelector(item) ?? 0).ToList(); - } - - // Determine the index to insert the dragged card. - int currentCardIndex = eventArgs.TargetIndex; - if (currentCardIndex >= 0 && currentCardIndex <= targetColumnItems.Count) - { - targetColumnItems.Insert(currentCardIndex, eventArgs.Data); - } - else - { - targetColumnItems.Add(eventArgs.Data); - currentCardIndex = targetColumnItems.Count - 1; - } - - // Update index property of all items using smart positioning logic - this.ApplySmartIndexUpdate(targetColumnItems, sortingOrder, currentCardIndex); -} - -/// -/// Method to get the property info for the specified property. -/// -private PropertyInfo? GetPropertyInfo(Type type, string key) -{ - return this.GetPropertyInfoCustomType(type, key); -} - -/// -/// Method to get the property info for the specified property from the given type. -/// -private PropertyInfo? GetPropertyInfoCustomType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type, string key) -{ - return type.GetProperty(key); -} - -/// -/// Updates index property with smart positioning based on sorting order. -/// -private void ApplySmartIndexUpdate(List items, KanbanSortingOrder sortingOrder, int currentCardIndex) -{ - if (items == null || items.Count == 0) - { - return; - } - - if (sortingOrder == KanbanSortingOrder.Ascending) - { - this.HandleAscendingIndexSorting(items, currentCardIndex); - return; - } - - this.HandleDescendingIndexSorting(items, currentCardIndex); -} +{% endhighlight %} +{% highlight c# tabtitle="CardDetails.cs" %} -/// -/// Method to handle ascending index sorting with smart positioning. -/// -private void HandleAscendingIndexSorting(List items, int currentCardIndex) +public class CardDetails { - int afterCardIndex = -1; - int lastItemIndex = -1; - - // Get the index of the card after the insertion point - if (currentCardIndex < items.Count - 1) - { - var afterCard = items[currentCardIndex + 1]; - afterCardIndex = GetCardIndex(afterCard) ?? -1; - } - - for (int i = 0; i < items.Count; i++) - { - var item = items[i]; - if (item == null) - { - continue; - } - - PropertyInfo? propertyInfo = this.GetPropertyInfo(item.GetType(), "Index"); - if (propertyInfo == null) - { - continue; - } - - int itemIndex = Convert.ToInt32(propertyInfo.GetValue(item) ?? 0); - bool isFirstItem = i == 0; - if (isFirstItem) - { - // If the inserted card is at the beginning, assign a smart index - if (currentCardIndex == 0) - { - lastItemIndex = afterCardIndex > 1 ? afterCardIndex - 1 : 1; - propertyInfo.SetValue(item, lastItemIndex); - } - else - { - lastItemIndex = itemIndex; - } - } - else - { - // Increment index for subsequent items - lastItemIndex++; - propertyInfo.SetValue(item, lastItemIndex); - } - } + public string? Title { get; set; } + public string? Description { get; set; } + public int? Index { get; set; } + public string? Category { get; set; } } -/// -/// Method to handle descending index sorting with smart positioning. -/// -private void HandleDescendingIndexSorting(List items, int currentCardIndex) -{ - int beforeCardIndex = -1; - int lastItemIndex = -1; - - // Get the index of the card before the insertion point - if (currentCardIndex > 0 && currentCardIndex < items.Count) - { - var cardBefore = items[currentCardIndex - 1]; - beforeCardIndex = GetCardIndex(cardBefore) ?? -1; - } - - for (int i = items.Count - 1; i >= 0; i--) - { - var item = items[i]; - if (item == null) - { - continue; - } - - PropertyInfo? propertyInfo = this.GetPropertyInfo(item.GetType(), "Index"); - if (propertyInfo == null) - { - continue; - } - - int itemIndex = Convert.ToInt32(propertyInfo.GetValue(item) ?? 0); - bool isLastItem = i == items.Count - 1; - if (isLastItem) - { - // If the inserted card is at the end, assign a smart index - if (currentCardIndex == items.Count - 1) - { - lastItemIndex = beforeCardIndex > 1 ? beforeCardIndex - 1 : 1; - propertyInfo.SetValue(item, lastItemIndex); - } - else - { - lastItemIndex = itemIndex; - } - } - else - { - lastItemIndex++; - propertyInfo.SetValue(item, lastItemIndex); - } - } -} +{% endhighlight %} +{% highlight c# tabtitle="SortingViewModel.cs" %} -/// -/// Method to get the index property value from a card object. -/// -private int? GetCardIndex(object cardDetails) +public class SortingViewModel { - if (cardDetails == null) - { - return null; - } - - PropertyInfo? propertyInfo = this.GetPropertyInfo(cardDetails.GetType(), "Index"); - if (propertyInfo == null) - { - return null; - } - - var indexValue = propertyInfo.GetValue(cardDetails); - if (indexValue != null) - { - return Convert.ToInt32(indexValue); - } - - return null; + public SortingViewModel() + { + this.Cards = new ObservableCollection() + { + new CardDetails() { Title = "Task - 1", Index = 5, Category = "Open", Description = "Fix the issue reported in the Edge browser." }, + new CardDetails() { Title = "Task - 3", Index = 9, Category = "In Progress", Description = "Analyze the new requirements gathered from the customer." }, + new CardDetails() { Title = "Task - 4", Index = 2, Category = "Open", Description = "Arrange a web meeting with the customer to get new requirements." }, + new CardDetails() { Title = "Task - 2", Index = 1, Category = "In Progress", Description = "Test the application in the Edge browser." }, + new CardDetails() { Title = "Task - 5", Index = 8, Category = "Done", Description = "Enhance editing functionality." }, + new CardDetails() { Title = "Task - 8", Index = 3, Category = "In Progress", Description = "Improve application performance." }, + new CardDetails() { Title = "Task - 9", Index = 6, Category = "Done", Description = "Improve the performance of the editing functionality." }, + new CardDetails() { Title = "Task - 10", Index = 4, Category = "Open", Description = "Analyze grid control." }, + new CardDetails() { Title = "Task - 12", Index = 7, Category = "Done", Description = "Analyze stored procedures." } + }; + } + + public ObservableCollection Cards { get; set; } } {% endhighlight %} {% endtabs %} -### ItemsSource Order - -The SortBy ItemsSource order approach does not require any SortingMappingPath value. In this behavior, cards are loaded based on the ItemsSource order, and also cards are dropped where the placeholder view is created exactly. \ No newline at end of file +N> + * The Index-based sorting can be achieved at the sample level after a drag-and-drop action. To implement this handle the `DragEnd` event, access the items in the target column using `e.TargetColumn.Items`, and update the numeric field used for sorting to maintain a continuous order. Finally, call `RefreshKanbanColumn` to update the UI with the new order. + * To disable sorting logic, avoid assigning a value to the `SortingMappingPath` property. This ensures that card positions remain static and reflect the order of the `ItemsSource` collection, making it suitable for scenarios where sorting is not required or is managed externally. \ No newline at end of file From 6b7cbcc4c623c8a2b0c830b346fbbf5888987191 Mon Sep 17 00:00:00 2001 From: AARTHI Date: Wed, 15 Oct 2025 20:28:43 +0530 Subject: [PATCH 6/7] 986416-Resolved CI error --- MAUI/Kanban-Board/Sorting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAUI/Kanban-Board/Sorting.md b/MAUI/Kanban-Board/Sorting.md index 837f24f7a3..3fd89a02b8 100644 --- a/MAUI/Kanban-Board/Sorting.md +++ b/MAUI/Kanban-Board/Sorting.md @@ -1,7 +1,7 @@ --- layout: post title: Sorting in .NET MAUI Kanban control | Syncfusion® -description: Learn here all about Sorting support in Syncfusion® .NET MAUI Kanban(SfKanban) control and more. +description: Learn here all about Sorting support in Syncfusion® .NET MAUI Kanban Board (SfKanban) control and more. platform: maui control: Kanban (SfKanban) documentation: ug From d9ef01becde946730c4e2d4a3659fec14c1271b4 Mon Sep 17 00:00:00 2001 From: AARTHI Date: Wed, 15 Oct 2025 21:08:31 +0530 Subject: [PATCH 7/7] 986416-Added code changes. --- MAUI/Kanban-Board/Sorting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAUI/Kanban-Board/Sorting.md b/MAUI/Kanban-Board/Sorting.md index 3fd89a02b8..40fdf15730 100644 --- a/MAUI/Kanban-Board/Sorting.md +++ b/MAUI/Kanban-Board/Sorting.md @@ -135,7 +135,7 @@ The following code example illustrates how cards numeric property updated using -