Datagrid validation

I do not think this works if the database updating is not being done via the EF Framework.

I have used your inline editing example, changing as little as possible (basically the class being used). I've included the page code and class/model here.

At no point, whether the edited column is valid or not, is the OnUpdateRow event triggered, so I cannot place my db update code there.

The SaveRow event is triggered whether the input is valid or invalid, so I cannot place my dbcode there either.

And I don't believe, from previous conversations, that I can check the messagestore from my code to see if the inputs are valid or not.

Can you offer any suggestions?

@page "/varieties"

@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
@inject DialogService DialogService
@inject ContextMenuService ContextMenuService
@inject TooltipService TooltipService
@inject NotificationService NotificationService

@inject VarietyService Varietyservice

@using System.ComponentModel.DataAnnotations;
@using Microsoft.EntityFrameworkCore;

<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="10px" class="mt-2 mb-4">
    <RadzenButton ButtonStyle="ButtonStyle.Success" Icon="add_circle_outline" Text="Add New Variety" Click="@InsertRow" Disabled="@(editMode == DataGridEditMode.Single && varietysToInsert.Count() > 0)" />
    <div style="white-space:nowrap; margin-left: 20px ">Edit Mode:</div>
    <RadzenSelectBar @bind-Value="@editMode" TextProperty="Text" ValueProperty="Value" style="margin-right: 16px"
                     Data="@(Enum.GetValues(typeof(DataGridEditMode)).Cast<DataGridEditMode>().Select(t => new { Text = $"{t}", Value = t }))" Size="ButtonSize.Small"
                     Disabled="@(editMode == DataGridEditMode.Multiple && varietysToInsert.Count() > 1)" />
</RadzenStack>

<RadzenDataGrid @ref="varietysGrid" AllowAlternatingRows="false" AllowFiltering="true" AllowPaging="true" PageSize="5" AllowSorting="true" EditMode="@editMode"
                Data="@varietys" TItem="Variety" RowUpdate="@OnUpdateRow" RowCreate="@OnCreateRow" Sort="@Reset" Page="@Reset" Filter="@Reset" ColumnWidth="200px">
    <Columns>
        <RadzenDataGridColumn TItem="Variety" Property="VAR_Id" Title="Variety ID" Width="120px" Frozen="true" />
        <RadzenDataGridColumn TItem="Variety" Property="VAR_Name" Title="Name" Width="200px">
            <EditTemplate Context="variety">
                <RadzenTextBox @bind-Value="variety.VAR_Name" Style="width:100%" Name="VAR_Name" />
                <RadzenRequiredValidator Text="Name is Required" Component="VAR_Name" Popup="true" />
                <RadzenLengthValidator Text="Name length must be between 5 and 50" Style="display:block; position:relative; z-index: 1"  Component="VAR_Name" Min="5" Max="50" Popup="true" />
            </EditTemplate>
        </RadzenDataGridColumn>
        <RadzenDataGridColumn TItem="Variety" Context="variety" Filterable="false" Sortable="false" TextAlign="TextAlign.Right" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
            <Template Context="variety">
                <RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@(args => EditRow(variety))" @onclick:stopPropagation="true">
                </RadzenButton>
                <RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(variety))" @onclick:stopPropagation="true">
                </RadzenButton>
            </Template>
            <EditTemplate Context="variety">
                <RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => SaveRow(variety))">
                </RadzenButton>
                <RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@((args) => CancelEdit(variety))">
                </RadzenButton>
                <RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(variety))">
                </RadzenButton>
            </EditTemplate>
        </RadzenDataGridColumn>
    </Columns>
</RadzenDataGrid>

@code {
    RadzenDataGrid<Variety> varietysGrid;
    IEnumerable<Variety> varietys;

    DataGridEditMode editMode = DataGridEditMode.Single;

    List<Variety> varietysToInsert = new List<Variety>();
    List<Variety> varietysToUpdate = new List<Variety>();

    public TbiResult res = new();

    void Reset()
    {
        varietysToInsert.Clear();
        varietysToUpdate.Clear();
    }

    void Reset(Variety variety)
    {
        varietysToInsert.Remove(variety);
        varietysToUpdate.Remove(variety);
    }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

            DBConnection con = new DBConnection();
            res = await con.ConnectToDB(false);

            var results = await(Varietyservice.GetAll(1,true,true));
            varietys = results.Item2;

            await con.DisconnectDB();
    }

    async Task EditRow(Variety variety)
    {
        if (editMode == DataGridEditMode.Single && varietysToInsert.Count() > 0)
        {
            Reset();
        }

        varietysToUpdate.Add(variety);
        await varietysGrid.EditRow(variety);
    }

    void OnUpdateRow(Variety variety)
    {
        Reset(variety);

        NotificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Detail = "OnUpdateRow" });      

        //dbContext.Update(variety);

        //dbContext.SaveChanges();
    }

    async Task SaveRow(Variety variety)
    {
        await varietysGrid.UpdateRow(variety);
        NotificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Detail = variety.VAR_Name });        
    }

    void CancelEdit(Variety variety)
    {
        Reset(variety);

        varietysGrid.CancelEditRow(variety);

        NotificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Detail = "CancelEdit" });      

       // var varietyEntry = variety; // = dbContext.Entry(variety);
       // if (varietyEntry.State == EntityState.Modified)
       // {
       //     varietyEntry.CurrentValues.SetValues(varietyEntry.OriginalValues);
       //     varietyEntry.State = EntityState.Unchanged;
       // }
    }

    async Task DeleteRow(Variety variety)
    {
        Reset(variety);

        if (varietys.Contains(variety))
        {
         //   dbContext.Remove<Variety>(variety);

         //   dbContext.SaveChanges();

            await varietysGrid.Reload();
        }
        else
        {
            varietysGrid.CancelEditRow(variety);
            await varietysGrid.Reload();
        }
    }

    async Task InsertRow()
    {
        if (editMode == DataGridEditMode.Single)
        {
            Reset();
        }

        var variety = new Variety();
        varietysToInsert.Add(variety);
        await varietysGrid.InsertRow(variety);
    }

    void OnCreateRow(Variety variety)
    {
//        dbContext.Add(variety);

  //      dbContext.SaveChanges();

        varietysToInsert.Remove(variety);
    }
}
using System.ComponentModel.DataAnnotations;

namespace Tbi.Data.Models
{
    public class Variety
    {
        public int VAR_Id { get; set; }

        [Required]
        [Length(5,50) ]
        public string VAR_Name { get; set; }

        public int VAR_COM_Id { get; set; }

        public string VAR_Status { get; set; }

        public Byte[] VAR_Timestamp { get; set; }
    }
}

Here is self-contained code demonstrating your case:


@inject NotificationService NotificationService

<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="10px" class="mt-2 mb-4">
    <RadzenButton ButtonStyle="ButtonStyle.Success" Icon="add_circle_outline" Text="Add New Variety" Click="@InsertRow" Disabled="@(editMode == DataGridEditMode.Single && varietysToInsert.Count() > 0)" />
    <div style="white-space:nowrap; margin-left: 20px ">Edit Mode:</div>
    <RadzenSelectBar @bind-Value="@editMode" TextProperty="Text" ValueProperty="Value" style="margin-right: 16px"
                     Data="@(Enum.GetValues(typeof(DataGridEditMode)).Cast<DataGridEditMode>().Select(t => new { Text = $"{t}", Value = t }))" Size="ButtonSize.Small"
                     Disabled="@(editMode == DataGridEditMode.Multiple && varietysToInsert.Count() > 1)" />
</RadzenStack>

<RadzenDataGrid @ref="varietysGrid" AllowAlternatingRows="false" AllowFiltering="true" AllowPaging="true" PageSize="5" AllowSorting="true" EditMode="@editMode"
                Data="@varietys" TItem="Variety" RowUpdate="@OnUpdateRow" RowCreate="@OnCreateRow" Sort="@Reset" Page="@Reset" Filter="@Reset" ColumnWidth="200px">
    <Columns>
        <RadzenDataGridColumn TItem="Variety" Property="VAR_Id" Title="Variety ID" Width="120px" Frozen="true" />
        <RadzenDataGridColumn TItem="Variety" Property="VAR_Name" Title="Name" Width="200px">
            <EditTemplate Context="variety">
                <RadzenTextBox @bind-Value="variety.VAR_Name" Style="width:100%" Name="VAR_Name" />
                <RadzenRequiredValidator Text="Name is Required" Component="VAR_Name" />
                <RadzenLengthValidator Text="Name length must be between 5 and 50" Component="VAR_Name" Min="5" Max="50" />
            </EditTemplate>
        </RadzenDataGridColumn>
        <RadzenDataGridColumn TItem="Variety" Context="variety" Filterable="false" Sortable="false" TextAlign="TextAlign.Right" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
            <Template Context="variety">
                <RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@(args => EditRow(variety))" @onclick:stopPropagation="true">
                </RadzenButton>
                <RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(variety))" @onclick:stopPropagation="true">
                </RadzenButton>
            </Template>
            <EditTemplate Context="variety">
                <RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => SaveRow(variety))">
                </RadzenButton>
                <RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@((args) => CancelEdit(variety))">
                </RadzenButton>
                <RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(variety))">
                </RadzenButton>
            </EditTemplate>
        </RadzenDataGridColumn>
    </Columns>
</RadzenDataGrid>

@code {
    RadzenDataGrid<Variety> varietysGrid;
    IEnumerable<Variety> varietys;

    DataGridEditMode editMode = DataGridEditMode.Single;

    List<Variety> varietysToInsert = new List<Variety>();
    List<Variety> varietysToUpdate = new List<Variety>();

    void Reset()
    {
        varietysToInsert.Clear();
        varietysToUpdate.Clear();
    }

    void Reset(Variety variety)
    {
        varietysToInsert.Remove(variety);
        varietysToUpdate.Remove(variety);
    }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        varietys = Enumerable.Range(0, 100).Select(i => new Variety() { VAR_Id = i, VAR_Name = $"Name{i}"});
    }

    async Task EditRow(Variety variety)
    {
        if (editMode == DataGridEditMode.Single && varietysToInsert.Count() > 0)
        {
            Reset();
        }

        varietysToUpdate.Add(variety);
        await varietysGrid.EditRow(variety);
    }

    void OnUpdateRow(Variety variety)
    {
        Reset(variety);

        NotificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Success, Detail = "OnUpdateRow" });
    }

    async Task SaveRow(Variety variety)
    {
        NotificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Info, Detail = $"Attempt to update with value: {variety.VAR_Name}" });

       await varietysGrid.UpdateRow(variety);
    }

    void CancelEdit(Variety variety)
    {
        Reset(variety);

        varietysGrid.CancelEditRow(variety);

        NotificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Info, Detail = "CancelEdit" });
    }

    async Task DeleteRow(Variety variety)
    {
        Reset(variety);

        if (varietys.Contains(variety))
        {
            await varietysGrid.Reload();
        }
        else
        {
            varietysGrid.CancelEditRow(variety);
            await varietysGrid.Reload();
        }
    }

    async Task InsertRow()
    {
        if (editMode == DataGridEditMode.Single)
        {
            Reset();
        }

        var variety = new Variety();
        varietysToInsert.Add(variety);
        await varietysGrid.InsertRow(variety);
    }

    void OnCreateRow(Variety variety)
    {
        varietysToInsert.Remove(variety);
    }

    public class Variety
    {
        public int VAR_Id { get; set; }

        public string VAR_Name { get; set; }

        public int VAR_COM_Id { get; set; }

        public string VAR_Status { get; set; }

        public Byte[] VAR_Timestamp { get; set; }
    }
}

And here is how it works:
dg-inline

DataGrid will not update the row and close the editing until validation result is true.

Good Morning enchev,

Thanks for this. The missing link in my understanding was where to place my actual database update code, which turns out to be in the OnUpdateRow event.

Thanks for the assistance.

Reg