Add State feature so it will be possible to programmatically save, load and change current state of the ListView.
For example, programmatically open/close item in Edit mode.
=============================
ADMIN EDIT
=============================
A workaround can be achieved using JSInterop
function TriggerClose() {
var btn = document.querySelector(".close-edit");
if (btn && btn.click) {
btn.click();
}
}
@inject IJSRuntime JSInterop
<TelerikButton OnClick="@CloseEdit">Close Edit</TelerikButton>
<TelerikListView Data="@ListViewData" Pageable="true"
OnCreate="@CreateHandler" OnDelete="@DeleteHandler" OnUpdate="@UpdateHandler"
OnEdit="@EditHandler" OnCancel="@CancelHandler">
<EditTemplate>
<div class="edit-template" style="border: 1px solid green; margin: 10px; padding: 10px; display: inline-block;">
<TelerikTextBox @bind-Value="@context.Name" Label="Name" /><br />
<TelerikDropDownList Data="@Teams" @bind-Value="@context.Team" />
<ListViewCommandButton Command="Save" Icon="save">Save</ListViewCommandButton>
<ListViewCommandButton Class="close-edit" Command="Cancel" Icon="cancel">Cancel</ListViewCommandButton>
</div>
</EditTemplate>
<Template>
<div style="border: 1px solid black; margin: 10px; padding: 10px; display: inline-block;">
Employee: @context.Id <br />
Name: @context.Name in team: @context.Team
<ListViewCommandButton Command="Edit" Icon="edit">Edit</ListViewCommandButton>
<ListViewCommandButton Command="Delete" Icon="delete">Delete</ListViewCommandButton>
</div>
</Template>
<HeaderTemplate>
<ListViewCommandButton Command="Add" Icon="plus">Add Employee</ListViewCommandButton>
<p>In this sample, the first item will not open for editing because of the code in the OnEdit handler</p>
</HeaderTemplate>
</TelerikListView>
@code{
List<Employee> ListViewData { get; set; }
List<string> Teams { get; set; }
async Task CloseEdit()
{
await JSInterop.InvokeVoidAsync("TriggerClose");
}
async Task UpdateHandler(ListViewCommandEventArgs args)
{
Employee item = (Employee)args.Item;
// perform actual data source operation here through your service
await MyService.Update(item);
// update the local view-model data with the service data
await GetListViewData();
}
async Task DeleteHandler(ListViewCommandEventArgs args)
{
Employee item = (Employee)args.Item;
// perform actual data source operation here through your service
await MyService.Delete(item);
// update the local view-model data with the service data
await GetListViewData();
}
async Task CreateHandler(ListViewCommandEventArgs args)
{
Employee item = (Employee)args.Item;
// perform actual data source operation here through your service
await MyService.Create(item);
// update the local view-model data with the service data
await GetListViewData();
}
async Task EditHandler(ListViewCommandEventArgs e)
{
Employee currItem = e.Item as Employee;
// prevent opening an item for editing on condition
if (currItem.Id < 2)
{
e.IsCancelled = true;
}
}
async Task CancelHandler(ListViewCommandEventArgs e)
{
Employee changedItem = e.Item as Employee;
// this is the item as the user edited it, but chose to cancel editing/inserting
Console.WriteLine($"user changed item {changedItem.Id} to have Name: {changedItem.Name} and Team: {changedItem.Team}");
}
// data and models follow
async Task GetListViewData()
{
ListViewData = await MyService.Read();
Teams = await MyService.GetTeams();
}
protected override async Task OnInitializedAsync()
{
await GetListViewData();
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Team { get; set; }
}
// the following static class mimics an actual data service that handles the actual data source
// replace it with your actual service through the DI, this only mimics how the API can look like and works for this standalone page
public static class MyService
{
private static List<Employee> _data { get; set; } = new List<Employee>();
private static List<string> _teams = new List<string> { "Sales", "Dev", "Support" };
public static async Task Create(Employee itemToInsert)
{
itemToInsert.Id = _data.Count + 1;
_data.Insert(0, itemToInsert);
}
public static async Task<List<Employee>> Read()
{
if (_data.Count < 1)
{
for (int i = 1; i < 50; i++)
{
_data.Add(new Employee()
{
Id = i,
Name = $"Name {i}",
Team = _teams[i % _teams.Count]
});
}
}
return await Task.FromResult(_data);
}
public static async Task<List<string>> GetTeams()
{
return await Task.FromResult(_teams);
}
public static async Task Update(Employee itemToUpdate)
{
var index = _data.FindIndex(i => i.Id == itemToUpdate.Id);
if (index != -1)
{
_data[index] = itemToUpdate;
}
}
public static async Task Delete(Employee itemToDelete)
{
_data.Remove(itemToDelete);
}
}
}