diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000000..eb5cfec430
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,552 @@
+# Blazor Code Style Guide
+
+This guide outlines best practices for Razor component development and documentation in Blazor.
+
+## Razor File Structure
+
+Use the following top-down order in `.razor` files:
+
+1. `@page`
+2. `@using`
+3. `@namespace`
+4. `@inherits`
+5. `@implements`
+6. `@inject`
+
+Insert `
-````
+
## See Also
diff --git a/components/filemanager/data-binding/hierarchical-data.md b/components/filemanager/data-binding/hierarchical-data.md
index 2cb836510e..a80df51fa9 100644
--- a/components/filemanager/data-binding/hierarchical-data.md
+++ b/components/filemanager/data-binding/hierarchical-data.md
@@ -14,7 +14,7 @@ This article explains how to bind the FileManager for Blazor to hierarchical dat
Hierarchical data means that the collection of child items is provided in a field of its parent's model:
-* The `Items` field contains a collection of all children including sub-folders and files. They will be rendered in the [Preview Pane](slug:filemanager-preview-pane) when the parent folder is selected.
+* The `Items` field contains a collection of all children including sub-folders and files. They will be rendered in the [FileManager View](slug:filemanager-views) when the parent folder is selected.
* The `Directories` field contains a collection of the subfolders of a directory. They will be rendered in the TreeView navigation pane. If there are `Directories` for a specific folder it will have an expand icon. The `HasDirectories` field can override this, however, but it is not required for hierarchical data binding.
diff --git a/components/filemanager/data-binding/overview.md b/components/filemanager/data-binding/overview.md
index f521daf2cf..6c765f6844 100644
--- a/components/filemanager/data-binding/overview.md
+++ b/components/filemanager/data-binding/overview.md
@@ -8,26 +8,20 @@ published: True
position: 0
---
-# FileManager Data Binding Basics
+# FileManager Data Binding Overview
-This article explains the different ways to provide data to a FileManager component and the properties related to data binding. Reviewing this article will explain the basics of how you can describe the hierarchy of items in your data source to the treeview component so they can render.
+This FileManager Data Binding section explains the different ways to provide data to a FileManager component and the properties related to data binding. This article describes what are the available (bindable) features of FileManager data items and how to map model properties to these features.
-@[template](/_contentTemplates/common/general-info.md#valuebind-vs-databind-link)
-
-First, review:
-
-* The available (bindable) [features of a FileManager items](#filemanager-item-features).
-* How to match fields in the model with the FileManager item [data bindings](#data-bindings).
+There are two data binding modes that the FileManager supports:
-There are two modes of providing data to a FileManager, and they both use the items' features. Once you are familiar with the current article, choose the data binding more you wish to use:
+* [Flat data](slug:filemanager-data-binding-flat-data)—a collection of self-referencing items with parent-child relationships.
+* [Hierarchical data](slug:filemanager-data-binding-hierarchical-data)—each item holds its children in a nested property.
-* [Flat data](slug:filemanager-data-binding-flat-data) - a collection of self-referencing items with parent-child relationships See the `Id` and `ParentId` settings.
-
-* [Hierarchical data](slug:filemanager-data-binding-hierarchical-data) - each item holds its children in a nested property. See the `Directories` setting.
+@[template](/_contentTemplates/common/general-info.md#valuebind-vs-databind-link)
## FileManager Item Features
-The FileManager has features that map to properties in the model. The following model uses property names that will work automatically, with no additional FileManager configuration:
+The FileManager extracts information about the displayed files and folders from properties in the model. The following flat data model uses property names that will work automatically, with no additional FileManager configuration:
````RAZOR
@using System.IO
@@ -225,62 +219,41 @@ The FileManager has features that map to properties in the model. The following
}
````
-The above model properties have the following meaning for the FileManager:
-
+The following section describes the meaning of the model properties for the FileManager.
-@[template](/_contentTemplates/common/parameters-table-styles.md#table-layout)
+## Data Bindings
-| Property | Description |
-| --- | --- |
-| **Item features** | |
-| `Name` | The name of the file. |
-| `Size` | The size of the file. |
-| `Path` | The path of the file. |
-| `Extension` | The extension of the file. |
-| `IsDirectory` | Whether the item is a directory. If its value is `false` the item is considered a file and not a directory. |
-| `DateCreated` | The creation date of the file. |
-| `DateCreateUtc` | The creation date of the file in UTC. Required. |
-| `DateModified` | The modification date of the file. |
-| `DateModifiedUtc` | The modification date of the file in UTC. Required. |
-| **Item relations** | |
-| `Id `| The unique identifier of the file. Required for [**binding to flat data**](slug:filemanager-data-binding-flat-data). |
-| `ParentId` | Identifies the file's parent. Required for [**binding to flat data**](slug:filemanager-data-binding-flat-data). Set to `null` for root items. Do *not* use `ParentId` with hierarchical data. |
-| `HasDirectories` | Determines whether the item has subdirectories. Required for binding to [**flat data**](slug:filemanager-data-binding-flat-data) If `true`, the directory will show an expand arrow. With [**hierarchical data**](slug:filemanager-data-binding-hierarchical-data), the FileManager renders expand icons based on `Directories`, but `HasDirectories` will take precedence. |
-| `Directories` | Defines the item subdirectories. Required for [binding to **hierarchical data**](slug:filemanager-data-binding-hierarchical-data).
-| `Items` | Defines all the subitems (directories and files) of the item. |
+All [FileManager item features](#fileManager-item-features) map to model properties. You define that relationship by providing the property name from which the corresponding information is taken. To do this, use the following parameters of the main `TelerikFileManager` tag:
-## Data Bindings
+@[template](/_contentTemplates/common/parameters-table-styles.md#table-layout)
-All [FileManager item features](#fileManager-item-features) map to model properties. The properties of a treeview item match directly to a field of the model the treeview is bound to. You provide that relationship by providing the name of the field from which the corresponding information is to be taken. To do this, in the main `TelerikFileManager` tag, use the parameters described below:
-
-| FileManager Parameter | Default Value |
-| --- | --- |
-| **Item features** | |
-| `NameField`| `"Name"` |
-| `SizeField`| `"Size"` |
-| `PathField`| `"Path"` |
-| `ExtensionField`| `"Extension"` |
-| `IsDirectoryField`| `"IsDirectoryField"` |
-| `DateCreatedField`| `"DateCreated"` |
-| `DateCreateUtcField`| `"DateCreateUtc"` |
-| `DateModifiedField`| `"DateModified"` |
-| `DateModifiedUtcField`| `"DateModifiedUtc"` |
-| **Item relations** | |
-| `IdField `| `"Id" ` |
-| `ParentIdField`| `"ParentId"` |
-| `HasDirectoriesField`| `"HasDirectories"` |
-| `DirectoriesField`| `"Directories"` |
-| `EntriesField`| `"Entries"` |
-
->important Do not use `ParentId` with hierarchical data. This will confuse the FileManager that it is bound to flat data and the component may not render any items. If the model must have a `ParentId` property, set `ParentIdField` to a non-existent property.
+| FileManager Parameter | Default Parameter Value (Model Property Name) | Model Property Type | Model Value Description |
+| --- | --- | --- | --- |
+| **Item features** | | | |
+| `NameField`| `"Name"` | `string` | The name of the file or folder, excluding the extension. |
+| `SizeField`| `"Size"` | `long` | The size of the file in bytes. |
+| `PathField`| `"Path"` | `string` | The path to the item, including the name and extension. |
+| `ExtensionField`| `"Extension"` | `string` | The item extension, starting with a dot `.` |
+| `IsDirectoryField`| `"IsDirectory"` | `bool` | Whether the item is a folder. If `false`, it's treated as a file. |
+| `DateCreatedField`| `"DateCreated"` | `DateTime` | The creation date of the file. |
+| `DateCreatedUtcField`| `"DateCreatedUtc"` | `DateTime` | The creation date of the file in UTC. Required. |
+| `DateModifiedField`| `"DateModified"` | `DateTime` | The modification date of the file. |
+| `DateModifiedUtcField`| `"DateModifiedUtc"` | `DateTime` | The modification date of the file in UTC. Required. |
+| **Item relations** | | | |
+| `IdField `| `"Id" ` | any | The unique identifier of the file. Required for [binding to flat data](slug:filemanager-data-binding-flat-data). |
+| `ParentIdField`| `"ParentId"` | any | Identifies the item's parent. Required for [binding to flat data](slug:filemanager-data-binding-flat-data). Set to `null` for root items. Do not use `ParentId` with hierarchical data. |
+| `HasDirectoriesField`| `"HasDirectories"` | `bool` | Determines whether the item has child folders. Required for [binding to flat data](slug:filemanager-data-binding-flat-data). If `true`, the folder will show an expand arrow in the TreeView. With [hierarchical data](slug:filemanager-data-binding-hierarchical-data), the FileManager renders expand icons based on `Directories`, but `HasDirectories` takes precedence. |
+| `DirectoriesField`| `"Directories"` | `IEnumerable` | The item's child folders to display in the TreeView. Required for [binding to hierarchical data](slug:filemanager-data-binding-hierarchical-data). |
+| `ItemsField`| `"Items"` | `IEnumerable` | The folder's child files and folders to display in the FileManager view. Required for [binding to hierarchical data](slug:filemanager-data-binding-hierarchical-data). |
+
+>important Do not use `ParentId` with hierarchical data. This will confuse the FileManager that it is bound to flat data and the component may not render any items. If the model must have a `ParentId` property, set `ParentIdField` to a non-existent property name.
## Next Steps
-Learn the different ways to provide data to a TreeView:
-
-* [Use flat data](slug:filemanager-data-binding-flat-data)
-* [Use hierarchical data](slug:filemanager-data-binding-hierarchical-data) - each item holds its children in a nested property
+Learn the different ways to provide data to a FileManager:
+* [Use flat data](slug:filemanager-data-binding-flat-data), where all items at all levels represent a single collection.
+* [Use hierarchical data](slug:filemanager-data-binding-hierarchical-data), where each folder item holds its child files and folders in nested properties.
## See Also
diff --git a/components/filemanager/events.md b/components/filemanager/events.md
index efa8976c12..487999bce9 100644
--- a/components/filemanager/events.md
+++ b/components/filemanager/events.md
@@ -12,20 +12,19 @@ position: 20
This article explains the events available in the Telerik FileManager for Blazor. They are grouped logically.
-* [CUD Events](#cud-events) - events related to Creating, Updating and Deleting items.
+* [CRUD Events](#crud-events) - events related to Creating, Updating and Deleting items.
* [OnCreate](#oncreate)
- * [OnUpdate](#onupdate)
- * [OnEdit](#onedit)
* [OnDelete](#ondelete)
-* [Read Event](#read-event) - event related to obtaining data.
-* [Other Events](#other-events) - other events the grid provides.
- * [OnModelInit](#onmodelinit)
- * [OnDownload](#ondownload)
- * [PathChanged](#pathchanged)
- * [SelectedItemsChanged](#selecteditemschanged)
- * [ViewChanged](#viewchanged)
+ * [OnEdit](#onedit)
+ * [OnUpdate](#onupdate)
+* [OnDownload](#ondownload)
+* [OnModelInit](#onmodelinit)
+* [OnRead Event](#onread) - event related to obtaining data.
+* [PathChanged](#pathchanged)
+* [SelectedItemsChanged](#selecteditemschanged)
+* [ViewChanged](#viewchanged)
-## CUD Events
+## CRUD Events
The `OnCreate`, `OnUpdate` and `OnDelete` events let you get the data item that the user changed so you can transfer the user action to the actual data source.
@@ -35,302 +34,27 @@ The `OnEdit` event let you respond to user actions - when they want to edit an i
The `OnCreate` event fires when a new item is created (new folder). Its event handler receives the updated `FileManagerCreateEventArgs` as an argument.
-### OnUpdate
-
-The `OnUpdate` event fires when a file is updated (rename finishes). Its event handler receives the updated `FileManagerUpdateEventArgs` as an argument.
-
-### OnEdit
-
-The `OnEdit` event fires when the user is about to enter edit mode for an existing item. Its event handler receives the updated `FileManagerEditEventArgs` as an argument.
-
### OnDelete
The `OnDelete` event fires when a file is deleted. Its event handler receives the updated `FileManagerDeleteEventArgs` as an argument.
-## Read Event
-
-In the common case, all the data is provided to the filemanager's `Data` collection and the `FileManager` performs the operations on it for you. In some cases, you may want to do this programmatically (for example, to retrieve only a small number of items to improve the backend performance). Attach the `OnRead` event to perform all the data read operations programmatically in the `FileManager`.
-
-The `OnRead` event fires when the data source is read. Its event handler receives the updated `FileManagerReadEventArgs` as an argument.
-
->caption Handle OnRead.
-
-````RAZOR
-@using System.IO
-
-
-
-
-@code {
- private List SourceData = new List();
-
- private string RootPath { get; set; } = "root-folder-path";
- private string DirectoryPath { get; set; } = "root-folder-path";
-
- private async Task OnRead(FileManagerReadEventArgs args)
- {
- await Task.Delay(500);
-
- //here you can pass only the files for the current directory, so you don't load the whole data collection
- args.Data = SourceData;
- args.Total = SourceData.Count;
- }
-
- private async Task OnUpdateHandler(FileManagerUpdateEventArgs args)
- {
- var item = args.Item as FlatFileEntry;
-
- if (item.IsDirectory)
- {
- // prevent renaming of directories. If you allow that, make sure
- //to also update the Path of the children
- }
- else
- {
- // simulate update of the file name and path
- var name = item.Name ?? string.Empty;
- var extension = item.Extension ?? string.Empty;
- var fullName = extension.Length > 0 && name.EndsWith(extension) ?
- name : $"{name}{extension}";
-
- var updatedItem = SourceData.FirstOrDefault(x => x.MyModelId == item.MyModelId);
-
- updatedItem.Name = item.Name;
- updatedItem.Path = Path.Combine(DirectoryPath, fullName);
- }
- }
-
- private async Task OnDownloadHandler(FileManagerDownloadEventArgs args)
- {
- var selectedItem = args.Item as FlatFileEntry;
-
- //the FileManager does not have the actual file.
- //To download it, find the actual file in the datasource
- //based on the selected file (args.Item) and
- //assign the following data to the argument:
-
- //args.Stream = the file stream of the actual selected file;
- //args.MimeType = the mime type of the actual file, so it can be downloaded;
- //args.FileName = allows overriding the name of the downloaded file;
- }
-
-
- private async Task OnDeleteHandler(FileManagerDeleteEventArgs args)
- {
- var currItem = args.Item as FlatFileEntry;
-
- var itemToDelete = SourceData.FirstOrDefault(x => x.MyModelId == currItem.MyModelId);
-
- //simulate item deletion
- SourceData.Remove(itemToDelete);
-
- RefreshData();
- }
-
- private FlatFileEntry OnModelInitHandler()
- {
- var item = new FlatFileEntry();
- item.Name = $"New folder";
- item.Size = 0;
- item.Path = Path.Combine(DirectoryPath, item.Name);
- item.IsDirectory = true;
- item.HasDirectories = false;
- item.DateCreated = DateTime.Now;
- item.DateCreatedUtc = DateTime.Now;
- item.DateModified = DateTime.Now;
- item.DateModifiedUtc = DateTime.Now;
-
- return item;
- }
-
- private void RefreshData()
- {
- SourceData = new List(SourceData);
- }
-
- // fetch the FileManager data
- protected override async Task OnInitializedAsync()
- {
- SourceData = await GetFlatFileEntries();
- }
-
- // a model to bind the FileManager. Should usually be in its own separate location.
- public class FlatFileEntry
- {
- public string MyModelId { get; set; }
- public string ParentId { get; set; }
- public string Name { get; set; }
- public long Size { get; set; }
- public string Path { get; set; }
- public string Extension { get; set; }
- public bool IsDirectory { get; set; }
- public bool HasDirectories { get; set; }
- public DateTime DateCreated { get; set; }
- public DateTime DateCreatedUtc { get; set; }
- public DateTime DateModified { get; set; }
- public DateTime DateModifiedUtc { get; set; }
- }
-
- // the next lines are hardcoded data generation so you can explore the FileManager freely
-
- private async Task> GetFlatFileEntries()
- {
- var workFiles = new FlatFileEntry()
- {
- MyModelId = "1",
- ParentId = null,
- Name = "Work Files",
- IsDirectory = true,
- HasDirectories = true,
- DateCreated = new DateTime(2022, 1, 2),
- DateCreatedUtc = new DateTime(2022, 1, 2),
- DateModified = new DateTime(2022, 2, 3),
- DateModifiedUtc = new DateTime(2022, 2, 3),
- Path = Path.Combine(RootPath, "Work Files"),
- Size = 3 * 1024 * 1024
- };
-
- var Documents = new FlatFileEntry()
- {
- MyModelId = "2",
- ParentId = workFiles.MyModelId,
- Name = "Documents",
- IsDirectory = true,
- HasDirectories = false,
- DateCreated = new DateTime(2022, 1, 2),
- DateCreatedUtc = new DateTime(2022, 1, 2),
- DateModified = new DateTime(2022, 2, 3),
- DateModifiedUtc = new DateTime(2022, 2, 3),
- Path = Path.Combine(workFiles.Path, "Documents"),
- Size = 1024 * 1024
- };
-
- var Images = new FlatFileEntry()
- {
- MyModelId = "3",
- ParentId = workFiles.MyModelId,
- Name = "Images",
- IsDirectory = true,
- HasDirectories = false,
- DateCreated = new DateTime(2022, 1, 2),
- DateCreatedUtc = new DateTime(2022, 1, 2),
- DateModified = new DateTime(2022, 2, 3),
- DateModifiedUtc = new DateTime(2022, 2, 3),
- Path = Path.Combine(workFiles.Path, "Images"),
- Size = 2 * 1024 * 1024
- };
-
- var specification = new FlatFileEntry()
- {
- MyModelId = "4",
- ParentId = Documents.MyModelId,
- Name = "Specification",
- IsDirectory = false,
- HasDirectories = false,
- Extension = ".docx",
- DateCreated = new DateTime(2022, 1, 5),
- DateCreatedUtc = new DateTime(2022, 1, 5),
- DateModified = new DateTime(2022, 2, 3),
- DateModifiedUtc = new DateTime(2022, 2, 3),
- Path = Path.Combine(Documents.Path, "Specification.docx"),
- Size = 462 * 1024
- };
-
- var report = new FlatFileEntry()
- {
- MyModelId = "5",
- ParentId = Documents.MyModelId,
- Name = "Monthly report",
- IsDirectory = false,
- HasDirectories = false,
- Extension = ".xlsx",
- DateCreated = new DateTime(2022, 1, 20),
- DateCreatedUtc = new DateTime(2022, 1, 20),
- DateModified = new DateTime(2022, 1, 25),
- DateModifiedUtc = new DateTime(2022, 1, 25),
- Path = Path.Combine(Documents.Path, "Monthly report.xlsx"),
- Size = 538 * 1024
- };
-
- var dashboardDesign = new FlatFileEntry()
- {
- MyModelId = "6",
- ParentId = Images.MyModelId,
- Name = "Dashboard Design",
- IsDirectory = false,
- HasDirectories = false,
- Extension = ".png",
- DateCreated = new DateTime(2022, 1, 10),
- DateCreatedUtc = new DateTime(2022, 1, 10),
- DateModified = new DateTime(2022, 2, 13),
- DateModifiedUtc = new DateTime(2022, 2, 13),
- Path = Path.Combine(Images.Path, "Dashboard Design.png"),
- Size = 1024
- };
-
- var gridDesign = new FlatFileEntry()
- {
- MyModelId = "7",
- ParentId = Images.MyModelId,
- Name = "Grid Design",
- IsDirectory = false,
- HasDirectories = false,
- Extension = ".jpg",
- DateCreated = new DateTime(2022, 1, 12),
- DateCreatedUtc = new DateTime(2022, 1, 12),
- DateModified = new DateTime(2022, 2, 13),
- DateModifiedUtc = new DateTime(2022, 2, 13),
- Path = Path.Combine(Images.Path, "Grid Design.jpg"),
- Size = 1024
- };
-
- var files = new List()
- {
- workFiles,
-
- Documents,
- specification,
- report,
+### OnEdit
- Images,
- dashboardDesign,
- gridDesign
- };
+The `OnEdit` event fires when the user is about to enter edit mode for an existing item. Its event handler receives the updated `FileManagerEditEventArgs` as an argument.
- return await Task.FromResult(files);
- }
-}
-````
+### OnUpdate
-## Other Events
+The `OnUpdate` event fires when a file is updated (rename finishes). Its event handler receives the updated `FileManagerUpdateEventArgs` as an argument.
-### OnModelInit
+## OnDownload
-The `OnModelInit` event fires when a new instance of the model is about to be created. Handle this event to allow the creation of a new folder/file. Provide an instance of the model that the component is bound to and include the desired properties (name, path, date of creation and more). See the [example](#example).
+The `OnDownload` event fires before a file download starts. The event is cancellable. The event handler argument is an `FileManagerDownloadEventArgs` object. See the [example](#example).
-### OnDownload
+### MIME Type
-The `OnDownload` event fires before a file download starts. The event is cancellable. The event handler argument is an `FileManagerDownloadEventArgs` object. See the [example](#example).
+The `FileManagerDownloadEventArgs` event argument has a `MimeType` property, which is `null` when the `OnDownload` event fires. .NET does not provide a built-in MIME type tool, so the application must set the correct MIME type, depending on the file extension or content. Consider [`Microsoft.AspNetCore.StaticFiles`](https://github.com/dotnet/aspnetcore/blob/main/src/Middleware/StaticFiles/src/FileExtensionContentTypeProvider.cs) or a similar tool.
-#### Downloading Large Files
+### Downloading Large Files
The files are downloaded with the help of a Base64 data URL, which is sent to the browser through `JSInterop`. JavaScript code generates an `` tag with an [object URL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static) on the web page and the tag is clicked programmatically, so that the browser shows its **Save File** dialog.
@@ -341,7 +65,7 @@ Large files (tens or hundreds of megabytes) may hit the browser's max data URL l
>tip You can also vote for the [FileManager feature request to expose a Proxy Url](https://feedback.telerik.com/blazor/1633629) for serving files from the server to the browser.
-#### Downloading Server Files in WebAssembly Apps
+### Downloading Server Files in WebAssembly Apps
A FileManager in a WebAssembly app usually displays files from a remote server. In such cases, use the following download approach:
@@ -349,15 +73,31 @@ A FileManager in a WebAssembly app usually displays files from a remote server.
1. The server returns the file content.
1. The `OnDownload` handler puts the returned file content to a `MemoryStream` and assigns it to `args.Stream`.
-### PathChanged
+## OnModelInit
+
+The `OnModelInit` event fires when a new instance of the model is about to be created. Handle this event to allow the creation of a new folder/file. Provide an instance of the model that the component is bound to and include the desired properties (name, path, date of creation and more). See the [example](#example).
+
+## OnRead
+
+The `OnRead` event is an alternative way to provide the FileManager with data, instead of the `Data` parameter. The event fires when the FileManager is initialized. The event handler receives a `FileManagerReadEventArgs` object as an argument.
+
+Use the `OnRead` event if you want to load chunks of FileManager data on demand. The following API members are required:
+
+* `PathChanged` event
+* `Rebind()` method
+* `OnRead` event
+
+For more information, refer to [How to Load FileManager File Data on Demand](slug:filemanager-kb-load-file-data-on-demand).
+
+## PathChanged
The `PathChanged` event fires when the user navigates to a different folder through the TreeView or by double-clicking a folder item in the [FileManager View](slug:filemanager-views). The event handler receives the new path as a `string` argument.
-### SelectedItemsChanged
+## SelectedItemsChanged
The `SelectedItemChanged` event fires every time the user clicks on a new file/folder in the main pane of the FileManager. You can use it with one-way binding of the `SelectedItems` parameter to respond to user selection.
-### ViewChanged
+## ViewChanged
The `ViewChanged` event fires when the user toggles between the [two FileManager views (`Grid` and `ListView`)](slug:filemanager-views). If you are using the event, make sure to update the value of the `View` parameter, otherwise the user action will have no effect.
@@ -477,24 +217,31 @@ The `ViewChanged` event fires when the user toggles between the [two FileManager
private async Task OnDownloadHandler(FileManagerDownloadEventArgs args)
{
- var selectedItem = args.Item as FlatFileEntry;
+ var downloadedFile = (FlatFileEntry)args.Item;
// The Filemanager does not have the actual file.
- // Obtain the file contents, based on args.Item, and set the event arguments:
+ // Obtain the file contents, based on args.Item, and set the event arguments.
+
+ // Get the full file path
+ //string filePathWithoutStartSeparator = downloadedFile.Path.IndexOf(Path.DirectorySeparatorChar) == 0 ? downloadedFile.Path.Substring(1) : downloadedFile.Path;
+ //string fullFilePath = Path.Combine(BasePath, filePathWithoutStartSeparator);
- //args.Stream = the file stream of the actual selected file;
- //args.MimeType = the MIME type of the actual file;
- //args.FileName = the file name that the browser will receive (optional);
+ // Create a MemoryStream with the file contents
+ //byte[] fileBytes = await System.IO.File.ReadAllBytesAsync(fullFilePath);
+ //MemoryStream fileStream = new(fileBytes);
- FlatFileEntry actualFile = (FlatFileEntry)args.Item;
+ // Set the event arguments
+ //args.FileName = string.Concat(downloadedFile.Name, downloadedFile.Extension);
+ //args.MimeType = "application/octet-stream";
+ //args.Stream = fileStream;
await Task.Delay(1); // simulate async operation
- string dummyFileContent = $"This file is a dummy version of {actualFile.Name}. It was downloaded with the Telerik Blazor FileManager.";
+ string dummyFileContent = $"This file is a dummy version of {downloadedFile.Name}. It was downloaded with the Telerik Blazor FileManager.";
byte[] dummyFileBuffer = System.Text.Encoding.UTF8.GetBytes(dummyFileContent);
args.Stream = new MemoryStream(dummyFileBuffer);
args.MimeType = "text/plain";
- args.FileName = $"filemanager-{actualFile.Name}-{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}.txt";
+ args.FileName = $"filemanager-{downloadedFile.Name}-{DateTime.Now.ToString("HH-mm-ss")}.txt";
}
private async Task OnDeleteHandler(FileManagerDeleteEventArgs args)
diff --git a/components/fileselect/events.md b/components/fileselect/events.md
index 9ca1be2164..b0659c79e4 100644
--- a/components/fileselect/events.md
+++ b/components/fileselect/events.md
@@ -27,7 +27,7 @@ The `FileSelectFileInfo` type contains the following properties:
Property | Type | Description
---------|----------|---------
`Id` | `string` | The unique file identifier.
-`Name`|`string` | The file name.
+`Name`|`string` | The encoded file name, including the extension. One method to decode it is [`System.Net.WebUtility.HtmlDecode()`](https://learn.microsoft.com/en-us/dotnet/api/system.net.webutility.htmldecode). The file can be renamed in the [`OnSelect` event handler](#onselect).
`Size` |`long` | The file size in bytes.
`Extension` |`string` | The file extension.
`InvalidExtension` | `bool` | A Boolean flag that shows if the file type is invalid.
diff --git a/components/filter/events.md b/components/filter/events.md
index a8dc8fe6ff..a11a675e6e 100644
--- a/components/filter/events.md
+++ b/components/filter/events.md
@@ -12,13 +12,67 @@ position: 11
This article explains the available events for the Telerik Filter for Blazor:
+* [OnUpdate](#onupdate)
* [ValueChanged](#valuechanged)
+## OnUpdate
+
+The `OnUpdate` event fires when the user changes the Filter `Value`. The component is designed for one-way binding and works directly with the object reference of the bound `CompositeFilterDescriptor`. The component updates the `Value` internally. Use the `OnUpdate` event to handle any additional logic when the Filter `Value` is modified.
+
+>caption Handle OnUpdate
+
+````RAZOR
+@using Telerik.DataSource
+
+
@code {
- public EditContext EditContext {get; set; }
- public Customer MyModel { get; set; } = new Customer();
- public CustomerValidator Validator { get; set; } = new CustomerValidator();
+ private Person PersonToEdit { get; set; } = new();
+
+ public PersonValidator PersonFluentValidator { get; set; } = new();
- protected override void OnInitialized()
+ private string FormSubmitResult { get; set; } = string.Empty;
+
+ private void LastNameChanged(string newLastName)
{
- EditContext = new EditContext(MyModel);
- base.OnInitialized();
+ PersonToEdit.LastName = newLastName;
}
- public class Customer
+ private void OnFormValidSubmit()
{
- public string FirstName { get; set; }
- public string LastName { get; set; }
+ FormSubmitResult = $"Form Submit Success at {DateTime.Now.ToString("HH:mm:ss")}";
+ }
+
+ public class PersonValidator : AbstractValidator
+ {
+ public PersonValidator()
+ {
+ RuleFor(customer => customer.FirstName).NotEmpty().MinimumLength(2).MaximumLength(60);
+ RuleFor(customer => customer.MiddleName).NotEmpty().MaximumLength(60);
+ RuleFor(customer => customer.LastName).NotEmpty().MinimumLength(2).MaximumLength(60);
+ }
+ }
+
+ public class Person
+ {
+ public int Id { get; set; }
+
+ public string FirstName { get; set; } = string.Empty;
+
+ public string MiddleName { get; set; } = string.Empty;
+
+ public string LastName { get; set; } = string.Empty;
}
+}
+````
+````RAZOR TextBox.razor
+@using System.Linq.Expressions
+
+
+
+@code {
+ [Parameter]
+ public string Value { get; set; } = string.Empty;
+
+ [Parameter]
+ public EventCallback ValueChanged { get; set; }
+
+ [Parameter]
+ public Expression>? ValueExpression { get; set; }
- public class CustomerValidator : AbstractValidator
+ [Parameter]
+ public string Id { get; set; } = string.Empty;
+
+ private async Task TextBoxValueChanged(string newValue)
{
- public CustomerValidator()
+ Value = newValue;
+
+ if (ValueChanged.HasDelegate)
{
- RuleFor(customer => customer.FirstName).NotEmpty().MaximumLength(50);
- RuleFor(customer => customer.LastName).NotEmpty().MaximumLength(50);
+ await ValueChanged.InvokeAsync(newValue);
}
}
}
diff --git a/components/gantt/gantt-tree/editing/incell.md b/components/gantt/gantt-tree/editing/incell.md
index a1b3e9d3ba..96e93d5a74 100644
--- a/components/gantt/gantt-tree/editing/incell.md
+++ b/components/gantt/gantt-tree/editing/incell.md
@@ -18,10 +18,18 @@ Command columns and non-editable columns are skipped while tabbing.
The InCell edit mode provides a specific user experience and behaves differently than other edit modes. Please review the notes below to get a better understanding of these specifics.
+## New Row Position
+
+To control whether a newly added item appears at the top or bottom of the Gantt Tree, set the `NewRowPosition` parameter.
+
+The `NewRowPosition` parameter accepts values from the `GanttTreeListNewRowPosition` enum:
+
+- `Top` (default)—Inserts the new item at the top of the view.
+- `Bottom`—Inserts the new item at the bottom of the view.
+
### Note
It is up to the data access logic to save the data once it is changed in the data collection, or to revert changes. The example above showcases the events that allow you to do that. In a real application, the code for handling data operations may be entirely different.
-
>caption InCell Editing Example.
````RAZOR
@@ -68,20 +76,9 @@ It is up to the data access logic to save the data once it is changed in the dat
@code {
- public DateTime SelectedDate { get; set; } = new DateTime(2019, 11, 11, 6, 0, 0);
-
- class FlatModel
- {
- public int Id { get; set; }
- public int? ParentId { get; set; }
- public string Title { get; set; }
- public double PercentComplete { get; set; }
- public DateTime Start { get; set; }
- public DateTime End { get; set; }
- }
-
- public int LastId { get; set; } = 1;
- List Data { get; set; }
+ private DateTime SelectedDate { get; set; } = new DateTime(2019, 11, 11, 6, 0, 0);
+ private int LastId { get; set; } = 1;
+ private List Data { get; set; }
protected override void OnInitialized()
{
@@ -122,6 +119,16 @@ It is up to the data access logic to save the data once it is changed in the dat
base.OnInitialized();
}
+ public class FlatModel
+ {
+ public int Id { get; set; }
+ public int? ParentId { get; set; }
+ public string Title { get; set; }
+ public double PercentComplete { get; set; }
+ public DateTime Start { get; set; }
+ public DateTime End { get; set; }
+ }
+
private async Task CreateItem(GanttCreateEventArgs args)
{
var argsItem = args.Item as FlatModel;
@@ -251,4 +258,3 @@ It is up to the data access logic to save the data once it is changed in the dat
## See Also
* [Live Demo: Gantt InCell Editing](https://demos.telerik.com/blazor-ui/gantt/editing-incell)
-
diff --git a/components/gantt/gantt-tree/editing/inline.md b/components/gantt/gantt-tree/editing/inline.md
index 55ca17ea03..690e11689c 100644
--- a/components/gantt/gantt-tree/editing/inline.md
+++ b/components/gantt/gantt-tree/editing/inline.md
@@ -20,6 +20,14 @@ You can also cancel the events by setting the `IsCancelled` property of the even
To enable Inline editing in the Gantt Tree, set its `TreeListEditMode` property to `GanttTreeListEditMode.Inline`, then handle the CRUD events as shown in the example below.
+## New Row Position
+
+To control whether a newly added item appears at the top or bottom of the Gantt Tree, set the `NewRowPosition` parameter.
+
+The `NewRowPosition` parameter accepts values from the `GanttTreeListNewRowPosition` enum:
+
+- `Top` (default)—Inserts the new item at the top of the view.
+- `Bottom`—Inserts the new item at the bottom of the view.
>caption The Command buttons and the Gantt events let you handle data operations in Inline edit mode.
@@ -70,20 +78,9 @@ To enable Inline editing in the Gantt Tree, set its `TreeListEditMode` property
@code {
- public DateTime SelectedDate { get; set; } = new DateTime(2019, 11, 11, 6, 0, 0);
-
- class FlatModel
- {
- public int Id { get; set; }
- public int? ParentId { get; set; }
- public string Title { get; set; }
- public double PercentComplete { get; set; }
- public DateTime Start { get; set; }
- public DateTime End { get; set; }
- }
-
- public int LastId { get; set; } = 1;
- List Data { get; set; }
+ private DateTime SelectedDate { get; set; } = new DateTime(2019, 11, 11, 6, 0, 0);
+ private int LastId { get; set; } = 1;
+ private List Data { get; set; }
protected override void OnInitialized()
{
@@ -124,6 +121,16 @@ To enable Inline editing in the Gantt Tree, set its `TreeListEditMode` property
base.OnInitialized();
}
+ public class FlatModel
+ {
+ public int Id { get; set; }
+ public int? ParentId { get; set; }
+ public string Title { get; set; }
+ public double PercentComplete { get; set; }
+ public DateTime Start { get; set; }
+ public DateTime End { get; set; }
+ }
+
private async Task CreateItem(GanttCreateEventArgs args)
{
var argsItem = args.Item as FlatModel;
diff --git a/components/gantt/gantt-tree/editing/overview.md b/components/gantt/gantt-tree/editing/overview.md
index b25d18813b..deacf14f0c 100644
--- a/components/gantt/gantt-tree/editing/overview.md
+++ b/components/gantt/gantt-tree/editing/overview.md
@@ -298,6 +298,30 @@ You can customize the editors rendered in the Gantt Tree by providing the `Edito
* `IsCanceled`- a boolean field indicating whether the operation is to be prevented.
+## New Row Position
+
+You can control whether a newly added item appears at the top or bottom of the Gantt Tree. Use the [`NewRowPosition`](https://www.telerik.com/blazor-ui/documentation/api/telerik.blazor.gantttreelistnewrowposition) parameter to specify the position. This parameter does not affect Popup edit mode, which always displays a dialog for new items.
+
+This configuration is available in InCell and Inline edit modes. For more details, see the [Tree InCell Editing](slug:gant-tree-incell-editing#new-row-position) and [Tree Inline Editing](slug:gant-tree-inline-editing#new-row-position) articles.
+
+> When you set `NewRowPosition` to `Bottom`, add the new item at the end of your data collection in the `OnCreate` event handler. When set to `Top`, insert the new item at the beginning of the collection. This ensures the new row appears in the correct position in the view after successfully creating the new record.
+
+>caption Example of adding a new item to the Gantt based on the `NewRowPosition` value
+
+
+````C#
+private void OnCreate(GanttCreateEventArgs args)
+{
+ if (NewRowPosition == GanttTreeListNewRowPosition.Bottom)
+ {
+ dataCollection.Add(newItem);
+ }
+ else // Top
+ {
+ dataCollection.Insert(0, newItem);
+ }
+}
+````
## Example
diff --git a/components/gauges/arc/labels.md b/components/gauges/arc/labels.md
index 48ece6bda1..0455af3ed6 100644
--- a/components/gauges/arc/labels.md
+++ b/components/gauges/arc/labels.md
@@ -13,13 +13,10 @@ position: 20
You can customize the appearance of the labels rendered on the [scale](slug:arc-gauge-scale) of the Arc Gauge by using the ``, child tag of the ``, and the parameters it exposes:
* [Format](#format)
-
* [Center Template](#center-template)
-
+* [Position](#position)
* [Color](#color)
-
* [Visible](#visible)
-
* [Additional Customization](#additional-customization)
## Format
@@ -87,6 +84,42 @@ The center template allows you to take control of the rendering of the central s
````
+## Position
+
+The `Position` parameter is of enum type `ArcGaugeScaleLabelsPosition` and determines whether the Gauge labels are on the inside (default) or outside of the Gauge graphic. Labels on the inside allow for a visually larger component within the same available space.
+
+>caption Setting Arc Gauge label position
+
+````RAZOR
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+````
+
## Color
The `Color` (`string`) parameter controls the color of the labels. It accepts **CSS**, **HEX** and **RGB** colors.
diff --git a/components/gauges/circular/labels.md b/components/gauges/circular/labels.md
index d5eca523e7..5551dc9714 100644
--- a/components/gauges/circular/labels.md
+++ b/components/gauges/circular/labels.md
@@ -13,13 +13,10 @@ position: 15
You can customize the appearance of the labels rendered on the [scale](slug:circular-gauge-scale) of the Circular Gauge by using the ``, child tag of the ``, and the parameters it exposes:
* [Format](#format)
-
* [Center Template](#center-template)
-
+* [Position](#position)
* [Color](#color)
-
* [Visible](#visible)
-
* [Additional Customization](#additional-customization)
## Format
@@ -91,6 +88,42 @@ The center template allows you to take control of the rendering of the central s
````
+## Position
+
+The `Position` parameter is of enum type `CircularGaugeScaleLabelsPosition` and determines whether the Gauge labels are on the inside (default) or outside of the Gauge graphic. Labels on the inside allow for a visually larger component on the same available space.
+
+>caption Setting Circular Gauge label position
+
+````RAZOR
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+````
+
## Color
The `Color` (`string`) parameter controls the color of the labels. It accepts **CSS**, **HEX** and **RGB** colors.
diff --git a/components/grid/editing/incell.md b/components/grid/editing/incell.md
index 570f0a1c36..b4dd5155e2 100644
--- a/components/grid/editing/incell.md
+++ b/components/grid/editing/incell.md
@@ -54,6 +54,17 @@ In in-cell edit mode, the `OnAdd` and `OnCreate` events fire immediately one aft
The above algorithm is different from [inline](slug:grid-editing-inline) and [popup](slug:grid-editing-popup) editing where new rows are only added to the data source after users populate them with valid values.
+## New Row Position
+
+You can control whether a newly added item appears at the top or bottom of the Grid. Use the `NewRowPosition` parameter to specify the position.
+
+The `NewRowPosition` parameter accepts values from the `GridNewRowPosition` enum:
+
+- `Top` (default)—Inserts the new item at the top of the view.
+- `Bottom`—Inserts the new item at the bottom of the view.
+
+For a complete example of how this feature works, see the following [example](slug:grid-editing-incell#basic).
+
## Integration with Other Features
Here is how the component behaves when the user tries to use add and edit operations together with other component features. Also check the [common information on this topic for all edit modes](slug:grid-editing-overview#integration-with-other-features).
@@ -72,6 +83,8 @@ This section explains what happens when the user tries to perform another data o
* If the validation is satisfied, then editing completes and the component fires `OnUpdate`.
* If the validation is not satisfied, then editing aborts and the component fires `OnCancel`.
+Deleting items that are currently in edit mode [fires `OnDelete` with a cloned data item instance](slug:grid-editing-overview#delete-operations).
+
### Selection
To enable [row selection](slug:grid-selection-row) with in-cell edit mode, use a [checkbox column](slug:components/grid/columns/checkbox). More information on that can be read in the [Row Selection](slug:grid-selection-row#selection-and-editing-modes) article.
diff --git a/components/grid/editing/inline.md b/components/grid/editing/inline.md
index 047e99ba57..a8022b2902 100644
--- a/components/grid/editing/inline.md
+++ b/components/grid/editing/inline.md
@@ -37,7 +37,16 @@ Inline add, edit, and delete operations use the following [command buttons](slug
In inline edit mode, the Grid commands execute row by row and the corresponding [Grid events](slug:grid-editing-overview#events) also fire row by row. This is similar to [popup editing](slug:grid-editing-popup) and unlike [in-cell editing](slug:grid-editing-incell), where commands and events relate to cells.
-When validation is not satisfied, clicking the **Save**, **Delete** or **Add** command buttons has no effect, but users can still navigate between all input components in the row to complete the editing.
+When validation is not satisfied, clicking the **Save**, **Delete** or **Add** command buttons have no effect, but users can still navigate between all input components in the row to complete the editing.
+
+## New Row Position
+
+You can control whether a newly added item appears at the top or bottom of the Grid. Use the `NewRowPosition` parameter to specify the position.
+
+The `NewRowPosition` parameter accepts values from the `GridNewRowPosition` enum:
+
+- `Top` (default)—Inserts the new item at the top of the view.
+- `Bottom`—Inserts the new item at the bottom of the view.
## Integration with Other Features
@@ -54,6 +63,8 @@ This section explains what happens when the component is already in add or edit
If the component is already in add or edit mode, and the user tries to perform another data operation, then editing aborts and the component fires `OnCancel`.
+Deleting items that are currently in edit mode [fires `OnDelete` with a cloned data item instance](slug:grid-editing-overview#delete-operations).
+
## Examples
### Basic
diff --git a/components/grid/editing/overview.md b/components/grid/editing/overview.md
index ead20360ca..02f76a10e7 100644
--- a/components/grid/editing/overview.md
+++ b/components/grid/editing/overview.md
@@ -35,6 +35,7 @@ The Grid CRUD operations rely on the following algorithm:
Adding or editing rows in the Grid sets the following requirements on the Grid model:
* The Grid model class must have a parameterless constructor. Otherwise, use the [Grid `OnModelInit` event](slug:grid-events#onmodelinit) to provide a data item instance [when the Grid needs to create one](#item-instances). Optinally, you can also [set some default values](slug://grid-kb-default-value-for-new-row).
+* There must be a non-editable property that serves as a unique identifier.
* All editable properties must be `public` and have setters. These properties must not be `readonly`.
* All complex properties used in the Grid must be instantiated in the [Grid `OnModelInit` event](slug:grid-events#onmodelinit).
* Self-referencing or inherited properties must not cause `StackOverflowException` or `AmbiguousMatchException` during [programmatic model instance creation](#item-instances).
@@ -79,6 +80,8 @@ Delete operations provide the same user experience in all Grid edit modes and re
Delete operations can work even if the Grid `EditMode` parameter value is `None`.
+If the Grid contains Delete command buttons that display and operate in edit mode, these buttons will fire the [`OnDelete` event](#events) with a [cloned data item instance](#item-instances) in the [event argument](#gridcommandeventargs). To find the original data item in the Grid data source, use the item ID or [override the `Equals()` method of the Grid model class](slug://grid-kb-editing-in-hierarchy).
+
>tip See the delete operations in action in the complete examples for Grid [inline](slug:grid-editing-inline#examples), [in-cell](slug:grid-editing-incell#examples), and [popup](slug:grid-editing-popup#examples) editing. Also check how to [customize the Delete Confirmation Dialog](slug:grid-kb-customize-delete-confirmation-dialog).
## Commands
@@ -97,7 +100,9 @@ Users execute commands in the following ways:
* By clicking on editable cells in [in-cell edit mode](slug:grid-editing-incell) and then anywhere else on the page.
* By using the [Grid keyboard navigation](https://demos.telerik.com/blazor-ui/grid/keyboard-navigation).
-Command buttons can only reside in a [Grid Command Column](slug:components/grid/columns/command) or the [Grid ToolBar](slug:components/grid/features/toolbar). You can also [trigger add and edit operations programmatically](slug:grid-kb-add-edit-state) from anywhere on the web page through the [Grid State](slug:grid-state).
+Command buttons can only reside in a [Grid Command Column](slug:components/grid/columns/command) or the [Grid ToolBar](slug:components/grid/features/toolbar). Each command button in the command column is visible only in display mode or only in edit mode, depending on the button's `ShowInEdit` boolean parameter value.
+
+You can also [trigger add and edit operations programmatically](slug:grid-kb-add-edit-state) from anywhere on the web page through the [Grid State](slug:grid-state).
## Events
@@ -110,7 +115,7 @@ The following table describes the Grid events, which are related to adding, dele
| `OnAdd` | No | Fires on `Add` [command button](slug://components/grid/columns/command) click, before the Grid enters add mode. This event preceeds `OnCreate` or `OnCancel`. | [New](#item-instances) | Grid remains in read mode. |
| `OnCancel` | No | Fires on `Cancel` command invocation. | [New or cloned](#item-instances) | Grid remains in add or edit mode. |
| `OnCreate` | To add new items. | Fires on `Save` command invocation for new items. This event succeeds `OnAdd`. | [New](#item-instances) | Grid remains in add mode. |
-| `OnDelete` | To [delete items](#delete-operations). | Fires on `Delete` command button click. | Original | Grid won't rebind. Deletion depends on the app itself. |
+| `OnDelete` | To [delete items](#delete-operations). | Fires on `Delete` command button click. | [Original or cloned](#item-instances) | Grid won't rebind. Deletion depends on the app itself. |
| `OnEdit` | No | Fires on `Edit` command invocation, before the Grid actually enters edit mode. This event preceeds `OnUpdate` or `OnCancel`. | Original | Grid remains in read mode. |
| `OnModelInit` | [Depends on the Grid model type](slug:grid-events#onmodelinit) | Fires when the Grid requires a [new model instance](#item-instances), which is immediately before `OnAdd` or immediately after `OnEdit`. Use this event when the Grid model type is an [interface, abstract class, or has no parameterless constructor](slug:grid-events#onmodelinit). | No event arguments | Not cancellable |
| `OnUpdate` | To edit existing items. | Fires on `Save` command invocation for existing items. This event succeeds `OnEdit`. | [Cloned](#item-instances) | Grid remains in edit mode. |
@@ -200,6 +205,32 @@ When editing a master row in a [hierarchy Grid](slug://components/grid/features/
Learn more integration details for the [inline](slug:grid-editing-inline#integration-with-other-features) and [in-cell](slug:grid-editing-incell#integration-with-other-features) edit modes.
+
+## New Row Position
+
+You can control whether a newly added item appears at the top or bottom of the Grid. Use the [`NewRowPosition`](https://www.telerik.com/blazor-ui/documentation/api/telerik.blazor.gridnewrowposition) parameter to specify the position. This parameter does not affect Popup edit mode, which always displays a dialog for new items.
+
+This configuration is available in InCell and Inline edit modes. For more details, see the [InCell Editing](slug:grid-editing-incell#new-row-position) and [Inline Editing](slug:grid-editing-inline#new-row-position) articles.
+
+> When you set `NewRowPosition` to `Bottom`, add the new item at the end of your data collection in the `OnCreate` event handler. When set to `Top`, insert the new item at the beginning of the collection. This ensures the new row appears in the correct position in the view after successfully creating the new record.
+
+>caption Example of adding a new item to the Grid based on the `NewRowPosition` value
+
+
+````C#
+private void OnCreate(GridCommandEventArgs args)
+{
+ if (NewRowPosition == GridNewRowPosition.Bottom)
+ {
+ dataCollection.Add(newItem);
+ }
+ else // Top
+ {
+ dataCollection.Insert(0, newItem);
+ }
+}
+````
+
## Examples
See Grid CRUD operations in action at:
diff --git a/components/grid/highlighting.md b/components/grid/highlighting.md
new file mode 100644
index 0000000000..9684f99fdd
--- /dev/null
+++ b/components/grid/highlighting.md
@@ -0,0 +1,116 @@
+---
+title: Highlighting
+page_title: Grid Highlighting
+slug: grid-highlighting
+description: Highlight rows and cells in the Telerik Blazor Grid to draw attention to important data.
+tags: telerik,blazor,grid,highlight,highlighting
+published: true
+position: 40
+---
+
+# Blazor Grid Highlighting
+
+The Telerik Blazor Grid enables you to highlight rows and cells programmatically. Use highlighting to draw attention to important data, indicate status, or visually group related records. Highlighting does not require user interaction and is fully controlled by the application logic.
+
+## Key Features
+
+* Highlight entire rows by providing a list of data items.
+* Highlight individual cells by specifying the data item and column.
+* Combine row and cell highlighting.
+* Highlighting uses a visual style similar to selection, but does not affect selection state or user interaction.
+
+To see the Grid highlighting in action, check the below [example](#example).
+
+## API Reference
+
+The Grid highlighting feature exposes the following parameters:
+
+- `HighlightedItems`—Highlight entire rows by providing the data items to highlight. The list must contain references to items from the grid's data source, not new instances.
+- `HighlightedCells`—Highlight individual cells by specifying both the data item and the column field. Both values must match the Grid data and column definitions.
+
+See [Grid Highlighting API Reference](slug:telerik.blazor.components.HighlightedCellDescriptor) for details about these parameters and the `GridHighlightedCellDescriptor` type.
+
+## Example
+
+>caption Example of highlighting rows and cells in the Blazor Grid
+
+````RAZOR
+
+
+
+
+
+
+
+
+
+
+
+@code {
+ private List GridData { get; set; } = new();
+ private List HighlightedItems { get; set; } = new();
+ private List HighlightedCells { get; set; } = new();
+
+ protected override void OnInitialized()
+ {
+ GenerateData();
+ SetHighlight();
+ }
+
+ private void SetHighlight()
+ {
+ // Highlight 5 items starting from the 3rd item in the data list
+ HighlightedItems = GridData.Skip(2).Take(5).ToList();
+
+ // Highlight specific cells: the ProductName of the first item and Discounted of the second item
+ HighlightedCells = new List
+ {
+ new GridHighlightedCellDescriptor
+ {
+ ColumnField = nameof(Product.ProductName),
+ DataItem = GridData[0]
+ },
+ new GridHighlightedCellDescriptor
+ {
+ ColumnField = nameof(Product.Discontinued),
+ DataItem = GridData[1]
+ }
+ };
+ }
+
+ private void GenerateData()
+ {
+ var random = new Random();
+ for (int i = 1; i <= 20; i++)
+ {
+ GridData.Add(new Product
+ {
+ ProductId = i,
+ ProductName = $"Product {i}",
+ UnitPrice = Math.Round(random.NextDouble() * 100, 2),
+ UnitsInStock = random.Next(1, 100),
+ CreatedAt = DateTime.Now.AddDays(-random.Next(1, 100)),
+ Discontinued = i % 5 == 0
+ });
+ }
+ }
+
+ public class Product
+ {
+ public int ProductId { get; set; }
+ public string ProductName { get; set; } = string.Empty;
+ public double UnitPrice { get; set; }
+ public int UnitsInStock { get; set; }
+ public DateTime CreatedAt { get; set; }
+ public bool Discontinued { get; set; }
+ }
+}
+````
+
+## See Also
+
+* [Grid Selection](slug:grid-selection-overview)
+* [Highlighting API Reference](slug:telerik.blazor.components.HighlightedCellDescriptor)
\ No newline at end of file
diff --git a/components/grid/overview.md b/components/grid/overview.md
index 1fdb9de86b..ff65765d96 100644
--- a/components/grid/overview.md
+++ b/components/grid/overview.md
@@ -5,6 +5,7 @@ description: The Blazor Grid provides a comprehensive set of ready-to-use featur
slug: grid-overview
tags: telerik,blazor,grid,datagrid,overview
published: True
+hideCta: True
position: 0
---
@@ -12,6 +13,8 @@ position: 0
This article provides a quick introduction to get your first Blazor data grid component up and running in a few seconds. There is a video tutorial and a list of the key features.
+Tired of reading docs? With our new AI Coding Assistants, you can add, configure, and troubleshoot Telerik UI for Blazor components—right inside your favorite AI-powered IDE: Visual Studio, VS Code, Cursor, and more. Start building faster, smarter, and with contextual intelligence powered by our docs/APIs:Try AI Assistants
+
The Telerik Blazor Data Grid provides a comprehensive set of ready-to-use features that cover everything from paging, sorting, filtering, editing, and grouping to row virtualization, optimized data reading, keyboard navigation, and accessibility support.
The Telerik Blazor grid is built on native Blazor from the ground up, by a company with a long history of making enterprise-ready Grids. This results in a highly customizable Grid that delivers lighting fast performance.
@@ -151,6 +154,7 @@ The Grid supports custom content in various parts of the component such as data
* [Drag and drop rows](slug:grid-drag-drop-overview)—move rows in a Grid or between different Grids.
* [Loading animation](slug:grid-loading)—show a loading animation to improve user experience during long data operations.
* Scrolling—the Grid will show standard scrollbars automatically if the data does not fit the current component width and height.
+* [Highlighting](slug:grid-highlighting)—highlight rows or cells programmatically to draw attention to important data.
## Grid Parameters
diff --git a/components/grid/selection/cells.md b/components/grid/selection/cells.md
index d57d3fd55e..d90f54bdbe 100644
--- a/components/grid/selection/cells.md
+++ b/components/grid/selection/cells.md
@@ -237,3 +237,4 @@ When using [Grid templates](slug:components/grid/features/templates) with cell s
* [Live Demo: Grid Cell Selection](https://demos.telerik.com/blazor-ui/grid/cell-selection)
* [Blazor Grid](slug:grid-overview)
+* [Grid Highlighting](slug:grid-highlighting)
diff --git a/components/grid/selection/rows.md b/components/grid/selection/rows.md
index 567060fce3..ed3fcef7a0 100644
--- a/components/grid/selection/rows.md
+++ b/components/grid/selection/rows.md
@@ -213,3 +213,4 @@ The Grid clears the `SelectedItems` collection when the user drags and drops sel
* [Live Demo: Grid Row Selection](https://demos.telerik.com/blazor-ui/grid/row-selection)
* [Blazor Grid](slug:grid-overview)
+* [Grid Highlighting](slug:grid-highlighting)
diff --git a/components/grid/state.md b/components/grid/state.md
index 049bc989f1..fb6c7f7b6d 100644
--- a/components/grid/state.md
+++ b/components/grid/state.md
@@ -43,7 +43,7 @@ The Grid state is a generic [class `GridState`](slug:Telerik.Blazor.Compo
| `SelectedItems` | `ICollection` | The currently [selected data item(s)](slug:grid-selection-overview). |
| `Skip` | `int?` | The number of scrolled data items when using [virtual row scrolling](slug:components/grid/virtual-scrolling). In other words, this is the number of rows above the currently visible ones. |
| `SortDescriptors` | `ICollection` | The currently applied [sorts](slug:components/grid/features/sorting). |
-| `TableWidth` | `string` | The sum of all visible column widths. This property changes together with `ColumnStates`. The `OnStateChanged` event does not fire separately for it. |
+| `TableWidth` | `string` | The sum of all visible column widths. The initial value is always `null` regardless of the column configuration. The `TableWidth` value changes during column resizing together with `ColumnStates` and the`OnStateChanged` event does not fire separately for it. When you resize a column programmatically, and all other columns already have widths, you must update the `TableWidth` too, otherwise the other columns will resize unexpectedly. |
\* `TItem` is the Grid model type.
diff --git a/components/grid/templates/editor.md b/components/grid/templates/editor.md
index 88c46218e8..d7e769dbf2 100644
--- a/components/grid/templates/editor.md
+++ b/components/grid/templates/editor.md
@@ -20,12 +20,13 @@ If you need more complex logic inside the editor template, compared to simple da
>tip The Editor Template works in all edit modes (Inline, Popup, InCell). Before using it with InCell mode, review the [pertinent notes](slug:grid-editing-incell#editor-template).
-When an input receives an `EditContext` (usually comes down as a cascading parameter), the framework also requires a `ValueExpression`. If you use two-way binding (the `@bind-Value` syntax), the `ValueExpression` is deducted from there. However, if you use only the `Value` property, you have to pass the `ValueExpression` yourself. This is a lambda expression that tells the framework what field in the model to update. The following sample demonstrates how to achieve that. You can also check the [Requires a value for ValueExpression](slug://common-kb-requires-valueexpression) knowledge base article for more details.
+When an input receives an `EditContext` (usually as a cascading parameter), the framework also requires a `ValueExpression`. If you use two-way binding (the `@bind-Value` syntax), the `ValueExpression` is deducted from there. However, if you use only the `Value` parameter, you have to pass the `ValueExpression` explicitly. This is a lambda expression that tells the framework what property of the model to use for validation. The following sample demonstrates how to achieve that. You can also check the [Requires a value for ValueExpression](slug:common-kb-requires-valueexpression) knowledge base article for more details.
````RAZOR
@@ -33,7 +34,6 @@ When an input receives an `EditContext` (usually comes down as a cascading param
@* Applies to the other input type components as well *@
````
-
**In this article:**
* [Notes](#notes)
@@ -46,39 +46,30 @@ When an input receives an `EditContext` (usually comes down as a cascading param
* @[template](/_contentTemplates/common/inputs.md#edit-debouncedelay)
-* The Grid row creates an `EditContext` and passes it to the `EditorTemplate`. You can read more about it in the [**Notes** section of the Editing Overview](slug:grid-editing-overview#notes) article.
-
* We recommend casting the Editor Template context to your model and storing it in a local or a dedicated global variable. Do not share a global variable within multiple templates, like column (cell) template and editor template. Variable sharing can lead to unexpected behavior.
-* Direct casting of the `context` can make the data binding not work properly.
-
-
->caption Not recommended: direct casting. Binding does not work properly.
+* Direct casting of the `context` can make two-way data binding not work properly.
-
+>caption Not recommended: direct casting with two-way parameter binding
-````RAZOR
+````RAZOR.skip-repl
````
->caption Recommended: cast the context to your model type and store it in a variable. Binding works as expected.
+>caption Recommended: cast the context in advance
````RAZOR
@{
- EditedProduct = context as Product;
+ var editProduct = (Product)context;
-
+
}
-
-@code{
- private Product EditedProduct { get; set; }
-}
````
## Examples
diff --git a/components/listview/overview.md b/components/listview/overview.md
index 1dc3d28d4b..082bf1a2f7 100644
--- a/components/listview/overview.md
+++ b/components/listview/overview.md
@@ -26,50 +26,7 @@ The Blazor
>caption ListView in read mode with paging enabled.
-````RAZOR
-@* Styles would usually go to to the site stylesheet, and you can read more details about
-the rest of the features the component provides further in this article *@
-
-
-
-