繁体   English   中英

更新列表<model>如果 UI 有任何变化,项目</model>

[英]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.

我看过你的项目。 代码和设计有很多错误。 我将在以某种方式起作用的代码下方显示。 复制并测试它。

索引.razor

@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>

索引.razor.cs

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");
    }
  }
}

记录.razor

@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 {

}

记录.razor.cs

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM