使用 select 元素时如何通过 @change="" 发送对象(而不是发送值)

How to send an object through @change="" (instead of sending value) when using select element

Blazor 新手,我有一个简单的问题

在我的 Blazor 应用中,我有一个简单的 select 元素:

<select class="form-select" aria-label="Default select example" @onchange="ItemSelected">
 <option selected>Open this select menu</option>
  
  @foreach(var item in Items)
  {
    <option value="@item.Id"> @item.Name </option>
  }
</select>

想法是当用户select有一个选项时,我想获取对象而不是密钥,这里是函数:

List<object> ItemContainer = new List<object>(); 
private void ItemSelected(ChangeEventArgs obj) {
  ...
  ItemContainer.Add(obj); 
}

如何捕获对象?

你不能直接。 ChangeEventArgs returns 字符串,因为它是 Value 对象。

你需要做这样的事情:

@page "/"

<select @onchange=OnSelect >
    @foreach (var country in Countries)
    {
        <option value="@country.Id" selected="@this.IsSelected(country)">@country.Name</option>
    }
</select>

<div>
    Selected : @this.SelectedCountry 
</div>

@code {
    private Country? country;
    private string SelectedCountry => this.country?.Name ?? "None Selected";

    protected override void OnInitialized()
    {
        // to demo selected is working
        this.country = this.Countries[1];
    }

    private void OnSelect(ChangeEventArgs e)
    {
        if (int.TryParse(e.Value?.ToString(), out int value))
            country = Countries.SingleOrDefault(item => item.Id == value);
    }

    private bool IsSelected(Country c)
        => c == this.country;

    public List<Country> Countries = new List<Country>
        {
            new Country { Id =44, Name = "UK" },
            new Country { Id =61, Name = "France" },
            new Country { Id =1, Name = "USA" },

        };

    public class Country
    {
        public int Id { get; set; }
        public string Name { get; set; } = string.Empty;
    }
}
@page "/"


<select @onchange="ItemSelected" class="form-select">
    <option value="null">Select...</option>

    @foreach (var option in options)
    {
        <option @key="option" value="@option.ID">@option.Value</option>
    }
</select>
       
  
@code {
    private Option option;

    private List<Option> options = Enumerable.Range(1, 10).Select(i => new Option { ID = i, Value = $"Option{i}" }).ToList();

    private void ItemSelected(ChangeEventArgs args)
    {
        if (int.TryParse(args.Value.ToString(), out int selectedID))
        {

            option = options.Where(o => o.ID == selectedID).FirstOrDefault();

            Console.WriteLine(option.ID.ToString());
            Console.WriteLine(option.Value);
        }
    }


    public class Option
    {
#nullable enable
        public int? ID { get; set; }
#nullable disable
        public string Value { get; set; }
    }

}

更新:

Hi, sorry for bothering you but I am stuck a bit on something. How do I avoid Option in my code? Because I already have an Item class private IEnumerable Items { get; set; } = new List(); is there a way to substitute both? thanks

Option是我给的class名字。你可以给它任何你想要的名字。您可以像下面这样定义 class:

public class ItemDTO
        {
    #nullable enable
            public int? Id { get; set; }
    #nullable disable
            public string Name{ get; set; }
        }

注意:如果您使用的是 .Net 6.0,则可以删除 #nullable 指令

更新:

不要使用 Task.Run 改变这个:

protected override async Task OnInitializedAsync()
    {
        await Task.Run(GetItems); 
        Client = _client.Get(Id);
    }
 
    private void GetItems()
    {
        Items = _item.GetAll();  
    }

收件人:

protected override void OnInitialized()
   {
        Client = _client.Get(Id);
        Items = _item.GetAll(); 
   }

改变这个:

private IEnumerable<ItemDTO> Items { get; set; } = new List<ItemDTO>(); 

收件人:

private IList<ItemDTO> Items { get; set; } = new List<ItemDTO>(); 

以上更改与其说是功能性的,不如说是装饰性的。我无法验证这一点,因为我只阅读了代码;我没有在 IDE.

中查看和 运行 它

无论如何,以下代码片段是不正确的,因此会导致错误:

var  option = ItemDTO.Where(o => o.Id == 
                                selectedID).FirstOrDefault();

上面的代码假设查询的是ItemDTO对象列表,return单个对象,其Id属性等于我们传递给方法(ItemSelected)的值,其中代码被执行。定义为 Items 的 ItemDTO 对象列表应用于搜索所选项目;也就是说,您应该使用:

`Items.Where` 

而不是:

ItemDTO.Where

ItemDTO 是 class 名称或类型...

您的代码应该是这样的:

var  option = Items.Where(o => o.Id == 
                                    selectedID).FirstOrDefault();

愿上帝保佑您的代码;}

抱歉,我现在打字不好,无法准确检查语法,但可能是这样的:

@onchange="(e)=> ItemSelected(Items.Single(i=> i.ID.ToString() == e.Value.ToString()))"

然后

private void ItemSelected(YourItemClass SelectedItem) {}