【问题标题】:Model properties not bind to dropdowns in Blazor模型属性未绑定到 Blazor 中的下拉菜单
【发布时间】:2022-01-25 10:32:52
【问题描述】:

我有 2 个级联下拉菜单:

问题是当我点击Save 按钮时,我的模型将为空。我不能在我的下拉列表中使用bind-value,因为我不能使用onchange 事件。只要绑定属性,我如何才能拥有级联功能。

代码:

@using Model

<select value="@MyLocation.CountryCode" @onchange="@CountryChanged">
@if (string.IsNullOrEmpty(MyLocation.CountryCode) == true)
{
     <option value="0" selected>[Choose One...]</option>
}

@foreach (var item in Countries)
{
     <option value="@item.Key">@item.Value</option>
}
</select>
<br />
<select value="@MyLocation.CityCode">
@foreach (var item in CountryCities)
{
     <option value="@item.Key">@item.Value</option>
}
</select>
<br />
<button class="btn btn-success" @onclick="() => HandleSave()">Save</button>

@code {

public Location MyLocation { get; set; } = new Location();
private Dictionary<string, string> Countries { set; get; } = new Dictionary<string, string>();
private Dictionary<string, string> CountryCities { set; get; } = new Dictionary<string, string>();

protected override Task OnInitializedAsync()
{
    Countries.Add("01", "Germany");
    Countries.Add("02", "Japan");
    Countries.Add("03", "England");

    return base.OnInitializedAsync();
}

private async Task CountryChanged(ChangeEventArgs e)
{
    CountryCities.Clear();
    switch (e.Value.ToString())
    {
        case "01":
            CountryCities.Add("001", "Munchen");
            break;
        case "02":
            CountryCities.Add("002", "Tokyo");
            break;
        case "03":
            CountryCities.Add("003", "Manchester");
            break;
    }
}

private void HandleSave()
{
    var Country = MyLocation.CountryCode; <--- CountryCode is null
}
}

【问题讨论】:

    标签: c# blazor blazor-webassembly


    【解决方案1】:
    @page "/"
    
    <select class="form-control" value="@MyLocation.CountryCode"
            @onchange="@((args) => { MyLocation.CountryCode = args.Value.ToString(); SelectCities(args); })">
    
        <option value="">Select Country...</option>
        @foreach (var country in countryList)
        {
            <option value="@country.Code"> @country.Name </option>
        }
     
    </select>
    <br />
    @if (cityList != null && cityList.Any())
    {
        <select class="form-control" @bind="@MyLocation.CityCode">
           <option value="">Select city...</option>
           @foreach (var city in cityList)
           {
                   <option value="@city.Code">@city.Name</option>
           }
        </select>
    }
        <br />
    
        <button class="btn btn-success" @onclick="() => HandleSave()">Save</button>
    
        @code {
    
            private Location MyLocation = new Location();
    
    
            private IList<Country> countryList = new List<Country>
      {
                new Country
                {
                    Code = "001", Name="USA",
                    Cities = new List<City> {  new City { Code = "1", Name = "City1" },
                             new City { Code = "2", Name = "City2" } }
                },
                new Country
                {
                    Code = "002", Name="Germany",
                    Cities = new List<City> {  new City { Code = "3", Name = "City1" },
                             new City { Code = "4", Name = "City2" } }
                },
                new Country
                {
                    Code = "003", Name="France",
                    Cities = new List<City> {  new City { Code = "5", Name = "City1" },
                             new City { Code = "6", Name = "City2" } }
                },
    
                new Country
                {
                    Code = "004", Name="UK",
                    Cities = new List<City> {  new City { Code = "7", Name = "City1" },
                             new City { Code = "8", Name = "City2" },
                             new City { Code = "9", Name = "City3" },
                             new City { Code = "10", Name = "City4" }}
                },
    
                new Country { Code = "005", Name="Russia",
                   Cities =  new List<City>  {  new City { Code = "11", Name = "City1" } }}
            };
    
    
            private IQueryable<City> cityList;
    
            private void HandleSave()
            {
                Console.WriteLine($"MyLocation.CountryCode: {MyLocation.CountryCode}");
                Console.WriteLine($"MyLocation.CityCode: {MyLocation.CityCode}");
             
            }
    
            private void SelectCities(ChangeEventArgs args)
            {
                // Note: Each time SelectCities is called MyLocation.CityCode should be set to null.
                MyLocation.CityCode = null;
                string countryCode = args.Value.ToString();
    
                cityList = (from country in countryList
                            where country.Code == countryCode
                            from city in country.Cities
                            select city).AsQueryable();
            }
    
            public class Location
            {
                public string CountryCode { get; set; }
                public string CityCode { get; set; }
    
            }
    
            public class Country
            {
                public string Code { get; set; }
                public string Name { get; set; }
    
                public IList<City> Cities { get; set; }
            }
    
            public class City
            {
                public string Code { get; set; }
                public string Name { get; set; }
    
            }
    
        }
    

    现在尝试将此代码转换为与嵌入在 EditForm 中的 Forms 的 InputSelect 组件一起使用

    【讨论】:

    • 谢谢亲爱的@enet。但有一个问题。例如,如果我选择UK 作为国家,并在City1 上留下城市下拉菜单并按Save,那么模型中的CityCode 值将为空...
    • 您可以使用问题中的代码:@if (string.IsNullOrEmpty(MyLocation.CityCode) == true) {
    • 解决此问题的最简单方法是将&lt;option value=""&gt;Select city...&lt;/option&gt; 添加到城市选择... 这会强制用户进行选择。我已经更新了我的答案。
    【解决方案2】:

    在 CountryChanged 方法上可以添加:

    MyLocation.CountryCode = e.Value.ToString();
    

    您可以对 CityCode 执行相同的操作:

    <select value="@MyLocation.CityCode" @onchange="@OnCityChanged">
    @foreach (var item in CountryCities)
    {
        <option value="@item.Key">@item.Value</option>
    }
    
    @code {
    private void OnCityChanged(ChangeEventArgs e) => MyLocation.CityCode = e.Value.ToString();
    }
    

    编辑:请注意,要使 OnCityChanged 起作用,用户必须实际选择一个值。如果他们不这样做,则第一个值(在您的情况下为 Muchen、Tokyo、Manchester)将不会在您的模型中设置为属性。对于这种情况,您可以在 CountryChanged 方法中执行类似操作:

    switch (e.Value.ToString())
        {
            case "01":
                CountryCities.Add("001", "Munchen");
                MyLocation.CityCode= "001";
                ...
    

    编辑 2:回复您的评论“谢谢,但我正在寻找输入文本中的绑定值之类的方法。”

    <EditForm Model="MyLocation">
    <InputSelect TValue="string" @bind-Value="MyLocation.CountryCode">
        @if (string.IsNullOrEmpty(MyLocation.CountryCode) == true)
        {
            <option value="0" selected>[Choose One...]</option>
        }
    
        @foreach (var item in Countries)
        {
            <option value="@item.Key">@item.Value</option>
        }
    </InputSelect>
    

    【讨论】:

    • 谢谢,但我正在输入文本中寻找类似bind-value 的方式。
    • 我编辑了我的答案以满足您的要求。
    • 再次感谢,但这导致我们失去了级联功能。你能指导我如何实现级联功能吗?我想根据所选国家/地区填写正确的项目。
    • 我相信 enet 的回答能满足你的需要!
    猜你喜欢
    • 2015-12-28
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多