[英]Update List<model> items if there are any changes in UI
如果不显示完整的概念,这有点难以解释,但我会尝试。 我在Record.razor.cs
- this.PersonellData
中有员工表。 我通过这种方法将新员工添加到表中:
private void AddNew()
{
this.PersonellData.Add(new Personell
{
Id = i + 1,
Name = "John " + i,
From = DateTime.Today + new TimeSpan(8, 30, 0),
Category = this.selectedCategoryValue,
});
this.DiaryRecord.Employees = new List<Personell>(this.PersonellData);
i++;
}
但是,在添加员工后,我想在 UI 中更改类别和(从)时间。 我可以在 UI 中做到这一点,但List<model>
本身的数据没有改变。 我在
private async Task OnCreateNewDiaryRecord()
{
if (true)
{
this.DiaryRecordModel = new DiaryRecord
{
Id = this.DiaryRecordModel.Id,
Title = this.DiaryRecordModel.Title,
Description = this.DiaryRecordModel.Description,
Employees = this.DiaryRecordModel.Employees,
Date = this.SelectedDate,
};
await OnInitializedAsync();
}
isDialogVisible = false;
}
在 Index.razor.cs 中,我没有在 UI 中对列表中的每个员工进行任何更改。 有什么建议如何让它工作吗? 我应该为每个 UI 项添加诸如 OnChange 之类的方法,但是如何继续更新实际列表?
这是 DiaryRecord.cs:
public class DiaryRecord
{
public Guid Id { get; set; }
public string Title { get; set; }
public ICollection<Personell> Employees { get; set; }
}
这是列表项的 UI 部分
<Table DataSource="this.PersonellData" RowClassName="@(_=>"editable-row")" Bordered Size=@TableSize.Small>
<Column Title="From" TData="DateTime">
<TimePicker TValue="DateTime?" @bind-Value="@context.From" OnChange="this.OnDateValueChanged" />
</Column>
<Column Title="Category" DataIndex="@nameof(context.Category)" TData="string">
<Select DataSource="@this.CategoryList"
@bind-Value="@this.selectedCategoryValue"
LabelName="@nameof(Category.CategorySymbol)"
ValueName="@nameof(Category.CategorySymbol)"
DefaultActiveFirstItem="false"
EnableSearch
OnSelectedItemChanged="this.OnSelectedCategoryChangedHandler">
</Select>
</Column>
</Table>
我已经尝试过OnChange="this.OnDateValueChanged"
,但不知道如何继续。
不要从您自己的代码中调用 OnInitializedAsync()。 当你这样做时,它不会触发 UI 更新。
//await OnInitializedAsync();
await InvokeAsync(StateHasChanged); // Invoke probably not needed. Just in case.
我看过你的项目。 代码和设计有很多错误。 我将在以某种方式起作用的代码下方显示。 复制并测试它。
@page "/"
@using AntDesign
<h1>Hello, world!</h1>
Welcome to your new app.
<br />
<br />
<Space>
<SpaceItem>
<Button Type="button" OnClick="@(()=>{ this.isDialogVisible = true; })">
Add Record
</Button>
</SpaceItem>
</Space>
<Space>
<Button Type="button" OnClick="Success">
Success
</Button>
</Space>
<Record DiaryRecord="DiaryRecordModel"></Record>
<Modal Title="Create new record"
Style="width:50%"
Visible="@this.isDialogVisible"
Footer="null"
Draggable="@(true)"
OnCancel="(e)=>{this.isDialogVisible = false;}">
<Form Model="this.DiaryRecordModel"
OnFinish="(e) => this.OnCreateNewDiaryRecord()">
<FormItem>
<Record DiaryRecord=this.DiaryRecordModel />
</FormItem>
<FormItem WrapperColOffset="8" WrapperColSpan="16">
<Button Type="@ButtonType.Primary" HtmlType="submit">
Submit
</Button>
<Button OnClick="(e)=>{this.isDialogVisible = false;}">Cancel</Button>
</FormItem>
</Form>
</Modal>
using AntDesign;
using BlazorAppAntDemo.Models;
using Microsoft.AspNetCore.Components;
using System;
using System.Threading.Tasks;
namespace BlazorAppAntDemo.Pages
{
public partial class Index
{
[Inject]
public MessageService Message { get; set; }
private DiaryRecord DiaryRecordModel { get; set; } = new DiaryRecord();
private bool isDialogVisible;
private DateTime SelectedDate { get; set; }
public Index()
{
this.DiaryRecordModel = new DiaryRecord();
this.DiaryRecordModel.Date = DateTime.Now;
}
protected override void OnInitialized()
{
}
private async Task OnCreateNewDiaryRecord()
{
if (true)
{
this.DiaryRecordModel = new DiaryRecord
{
Id = this.DiaryRecordModel.Id,
Title = this.DiaryRecordModel.Title,
Description = this.DiaryRecordModel.Description,
Employees = this.DiaryRecordModel.Employees,
Date = this.SelectedDate,
};
// await OnInitializedAsync();
await Task.Yield();
}
isDialogVisible = false;
}
private async Task Success()
{
await this.Message.Success("This is a success message");
}
}
}
@page "/record"
@using BlazorAppAntDemo.Models
<Template>
<Collapse DefaultActiveKey="@(new[] { "1" })"
OnChange="this.Callback"
ExpandIconPosition="@this.ExpandIconPosition"
ExpandIcon="caret-right">
<Panel Header="Basic information" Key="1">
<Form Model="DiaryRecord">
<FormItem Label="Record title" NoStyle>
<Input @bind-Value="@this.DiaryRecord.Title" />
</FormItem>
<FormItem Label="Description" NoStyle>
<Input @bind-Value="@this.DiaryRecord.Description" />
</FormItem>
<FormItem Label="Date" NoStyle>
<DatePicker @bind-Value="@this.DiaryRecord.Date" ShowTime="@true" OnChange="this.OnDateSelected" />
</FormItem>
</Form>
</Panel>
<Panel Header="Personell" Key="2">
<ChildContent>
<Button OnClick="this.AddNew" Type="button" Style="margin-bottom:16px">
Add person
</Button>
<Table DataSource="this.PersonellData" RowClassName="@(_=>"editable-row")" Bordered Size=@TableSize.Small>
<Column Title="Id" DataIndex="@nameof(context.Id)" TData="int"></Column>
<Column Title="Name" DataIndex="@nameof(context.Name)" TData="string"></Column>
<Column Title="From" TData="DateTime">
<TimePicker TValue="DateTime?" @bind-Value="@context.From" OnChange="this.OnDateValueChanged" />
</Column>
<Column Title="Category" DataIndex="@nameof(context.Category)" TData="string">
<Select DataSource="@this.CategoryList"
@bind-Value="@this.selectedCategoryValue"
LabelName="@nameof(Category.CategorySymbol)"
ValueName="@nameof(Category.CategorySymbol)"
DefaultActiveFirstItem="false"
EnableSearch
OnSelectedItemChanged="this.OnSelectedCategoryChangedHandler">
</Select>
</Column>
<ActionColumn Title="Action">
<Popconfirm Title="Sure to delete?"
OnConfirm="()=> this.Delete(context.Id)"
OkText="Yes"
CancelText="No">
<Button Danger>Delete</Button>
</Popconfirm>
</ActionColumn>
</Table>
</ChildContent>
</Panel>
<Panel Header="Attachments" Key="3">
<ChildContent>
<span class="ant-upload-picture-card-wrapper">
<label class="avatar-uploader" for="upload">
<div class="ant-upload ant-upload-select-picture-card ant-upload-select">
<div tabindex="0" class="ant-upload" style="position:relative;">
<InputFile OnChange="@this.OnFileSelection" multiple id="upload" hidden accept=".png,.jpg,.jpeg,.gif" />
<div class="row">
@if (this.ImgUrls.Any())
{
@foreach (var url in this.ImgUrls)
{
<div>
<img src="@url" alt="avatar" style="width: 100%" />
</div>
}
}
else
{
<div>
<Icon Spin="this.loading" Type="@(this.loading?"Loading":"plus")"></Icon>
<div className="ant-upload-text">Upload</div>
</div>
}
</div>
</div>
</div>
</label>
</span>
</ChildContent>
</Panel>
<Panel Header="Another one 1" Key="4">
<ChildContent>
<h3>Hola</h3>
</ChildContent>
</Panel>
<Panel Header="Another one 2" Key="5">
<ChildContent>
<h3>Hola 2</h3>
</ChildContent>
</Panel>
<Panel Header="Another one 3" Key="6">
<ChildContent>
<h3>Hola 3</h3>
</ChildContent>
</Panel>
</Collapse>
</Template>
@code {
}
using AntDesign;
using BlazorAppAntDemo.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BlazorAppAntDemo.Pages
{
public partial class Record
{
[Inject] private MessageService Message { get; set; }
[Inject] private NotificationService Notice { get; set; }
private string ExpandIconPosition { get; set; }
private int i = 1;
private List<Category> CategoryList { get; set; }
private string selectedCategoryValue;
private IQueryable<Personell> PersonellData { get; set; }
private List<string> ImgUrls { get; set; }
private List<FileData> FileData { get; set; }
private string imageUrl;
private int maxFileSize;
private byte[] profilePictureByteArray;
private bool loading;
[Parameter] public DiaryRecord DiaryRecord { get; set; }
public Record()
{
this.ExpandIconPosition = "left";
this.PersonellData = new List<Personell>().AsQueryable();
this.CategoryList = new List<Category>();
this.ImgUrls = new List<string>();
this.FileData = new List<FileData>();
this.maxFileSize = 400000;
}
protected override void OnInitialized()
{
this.CategoryList.Add(new Category { CategoryName = "CategoryA", CategorySymbol = "A" });
this.CategoryList.Add(new Category { CategoryName = "CategoryB", CategorySymbol = "B" });
this.CategoryList.Add(new Category { CategoryName = "CategoryC", CategorySymbol = "C" });
this.CategoryList.Add(new Category { CategoryName = "CategoryD", CategorySymbol = "D" });
}
private void AddNew()
{
this.PersonellData.Append(new Personell
{
Id = i + 1,
Name = "John " + i,
From = DateTime.Today + new TimeSpan(7, 30, 0),
Category = this.selectedCategoryValue,
});
this.DiaryRecord.Employees = new List<Personell>(this.PersonellData);
i++;
}
private void Delete(int id)
{
this.PersonellData = this.PersonellData.Where(d => d.Id != id);
}
private void OnSelectedCategoryChangedHandler(Category value)
{
this.selectedCategoryValue = value.CategoryName;
}
private void OnDateValueChanged()
{
}
private void OnDateSelected(DateTimeChangedEventArgs args)
{
this.DiaryRecord.Date = args.Date;
}
private void Callback(string[] keys)
{
}
private async Task OnFileSelection(InputFileChangeEventArgs e)
{
foreach (IBrowserFile file in e.GetMultipleFiles(this.maxFileSize))
{
if (file.Size < this.maxFileSize)
{
IBrowserFile imgFile = file;
this.profilePictureByteArray = new byte[imgFile.Size];
await imgFile.OpenReadStream().ReadAsync(profilePictureByteArray);
string imageType = imgFile.ContentType;
this.imageUrl = $"data:{imageType};base64,{Convert.ToBase64String(profilePictureByteArray)}";
this.ImgUrls.Add(imageUrl);
this.FileData.Add(new FileData
{
Data = profilePictureByteArray,
FileType = imageType,
Size = imgFile.Size
});
}
else
{
await Message.Error("File is too large!", 5);
await this.Notice.Open(new NotificationConfig()
{
Message = "title",
Duration = 0,
Description = "File is too large!"
});
}
}
}
}
}
您还应该添加<AntContainer />
,可能在 App 组件 (App.razor) 的顶部
注意:我在 Net5.0 中运行了您的代码,您必须在其中告诉编译器给定类型可以单独为空。 因为我不想浪费时间,所以我删除了可空性。 如果您有一些与此相关的问题,请告诉我。 我的代码有效,但不完整
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.