I have a radzen Datagrid defined. nothing too fancy or complex, just columns and basic edit template for each.
<RadzenDataGrid @ref=@bulkPriceGrid Data="@BulkPrice" TItem="BulkPrice">
<Columns>
<RadzenDataGridColumn TItem="BulkPrice" Property="StartingCount" Title="Starting Count" SortOrder="SortOrder.Ascending">
<EditTemplate Context="price">
<RadzenNumeric @bind-Value=@price.StartingCount Step="100" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="BulkPrice" Property="EndingCount" Title="Ending Count">
<EditTemplate Context="price">
<RadzenNumeric @bind-Value=@price.EndingCount Step="100" />
</EditTemplate>
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="BulkPrice" Property="Price" Title="Cost">
<EditTemplate Context="price">
<RadzenNumeric @bind-Value=@price.Price />
</EditTemplate>
</RadzenDataGridColumn>
<AuthorizeView Roles="BOM.Write" Context="AuthBomWrite">
<RadzenDataGridColumn TItem="BulkPrice" Context="price" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
<Template Context="price">
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@(args => EditRow(price))" @onclick:stopPropagation="true" />
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(price))" @onclick:stopPropagation="true" />
</Template>
<EditTemplate Context="price">
<RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => SaveRow(price))" />
<RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@((args) => CancelEdit(price))" />
<RadzenButton ButtonStyle="ButtonStyle.Danger" Icon="delete" Variant="Variant.Flat" Shade="Shade.Lighter" Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(args => DeleteRow(price))" />
</EditTemplate>
</RadzenDataGridColumn>
</AuthorizeView>
</Columns>
</RadzenDataGrid>
<RadzenButton ButtonStyle="ButtonStyle.Success" Icon="add_circle_outline" Text="Add New Bulk Threshold" Style="margin-top: 10px"
Disabled=@(priceToInsert != null || priceToUpdate != null) Click="AddNewPrice" />
here is the backing code
@code {
[Parameter]
public string Title { get; set; }
[Parameter]
public List<BulkPrice> BulkPrice { get; set; }
[Parameter]
public string Style { get; set; }
private RadzenDataGrid<BulkPrice>? bulkPriceGrid;
private BulkPrice? priceToInsert, priceToUpdate = null;
private void Reset()
{
priceToInsert = null;
priceToUpdate = null;
}
private async Task AddNewPrice()
{
priceToInsert = new BulkPrice();
priceToInsert.Changes = EChangeable.New;
await bulkPriceGrid.InsertRow(priceToInsert);
}
private async Task EditRow(BulkPrice price)
{
priceToUpdate = new BulkPrice(price);
await bulkPriceGrid.EditRow(price);
StateHasChanged();
}
private void DeleteRow(BulkPrice price)
{
Reset();
BulkPrice.Remove(price);
}
private async Task SaveRow(BulkPrice price)
{
Reset();
await bulkPriceGrid.UpdateRow(price);
BulkPrice.Add(price);
await bulkPriceGrid.RefreshDataAsync();
StateHasChanged();
}
private async Task CancelEdit(BulkPrice price)
{
var tempPrice = priceToUpdate;
Reset();
bulkPriceGrid.CancelEditRow(price);
var priceIndex = BulkPrice.IndexOf(price);
if (priceIndex < 0)
return;
BulkPrice.Remove(price);
BulkPrice.Insert(priceIndex, tempPrice);
await bulkPriceGrid.RefreshDataAsync();
}
private void FieldChanged(Changeable obj)
{
obj.Changes = EChangeable.Updated;
}
private void CellRender(CellRenderEventArgs<BulkPrice> args)
{
args.Attributes.Add("class", $"changeable-{args.Data.Changes.ToString()}");
}
}
the model being represented is simple as well
public sealed class BulkPrice : Changeable
{
public Guid BulkPriceId { get; set; } = Guid.NewGuid();
public int StartingCount { get; set; }
public int EndingCount { get; set; }
public decimal Price { get; set; }
public BulkPrice() { }
public BulkPrice(BulkPrice newPrice)
{
StartingCount = newPrice.StartingCount;
EndingCount = newPrice.EndingCount;
Price = newPrice.Price;
Changes = newPrice.Changes;
}
public override bool Equals(object? obj)
{
if(obj == null) return false;
if(ReferenceEquals(obj, this)) return true;
if(obj.GetType() != GetType()) return false;
BulkPrice other = obj as BulkPrice;
return StartingCount == other.StartingCount
&& EndingCount == other.EndingCount
&& Price == other.Price
&& Changes == other.Changes
&& BulkPriceId == other.BulkPriceId;
}
public override int GetHashCode()
{
return HashCode.Combine(BulkPriceId, StartingCount, EndingCount, Price, Changes);
}
public enum EChangeable
{
None,
New,
Updated,
Removed
}
public abstract class Changeable
{
private EChangeable _changes = EChangeable.None;
public EChangeable Changes { get => _changes;
set
{
if (value == EChangeable.None) { _changes = EChangeable.None; }
else if (value == EChangeable.Removed) { _changes = value; }
else if (value == EChangeable.New) { _changes = value; }
else if (value == EChangeable.Updated && _changes == EChangeable.None) { _changes = value; }
}
}
}
}
what makes this bulk price class unique is that the equals and gethashcode methods have been overridden. this shouldn't be a problem but what I'm encountering is that when I go to add a new row to the datagrid, the defaults work fine and I can click the checkbox that saves the object (row/record). but if I make any changes to the values before i click the checkbox, i get an error in the SaveRow
method on instruction await bulkPriceGrid.UpdateRow(price)
. the error being
System.Collections.Generic.KeyNotFoundException: The given key 'MyNameSpace.BulkPrice' was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Radzen.Blazor.RadzenDataGrid`1.UpdateRow(TItem item)
at MyNameSpace.BulkPriceComponent.SaveRow(BulkPrice price)
This error points to some the datagrid not using the same hash value as what my object generates. If I comment out the equals and gethashcode methods, it works fine.