【问题标题】:Dynamically binding input-text to class/object propertys using Blazor使用 Blazor 将输入文本动态绑定到类/对象属性
【发布时间】:2020-06-04 23:15:24
【问题描述】:

我正在尝试使用 Blazor 为类中的属性构建输入字段的动态列表,但无法弄清楚如何将输入框的内容绑定/链接到类的属性。 (该类可以有大量的公共属性,不仅仅是下面例子中的名称和描述,它们并不总是“字符串”类型)

假设我有这个类/模型:

public class customer{
        public string Name { get; set; }
        public int Age { get; set; }
        public string Description { get; set; }

}

我得到了这个 blazor 组件(updateC.razor):

@inherits CLogic    
@if (nfo != null)
{
      @foreach (var obj in nfo)
      {
             <input type="text" class="form-control"      
             bind=@SCustomer.GetType().GetProperty(obj.ToString())/>
      }
}

最后是 Clogic:

public class Clogic: ComponentBase{
    [Parameter]
    public Customer SCustomer { get; set; } = new Customer();
    [Parameter]
    public PropertyInfo[] nfo { get; set; }

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            nfo = SCustomer.GetType().GetProperties();
            StateHasChanged();
        }
    }
}

这是假设将每个输入字段中所做的更改绑定到当前 SCustomer 实例中的正确属性(输入时,假设更新类/对象的正确属性) .这不起作用,SCustomer 内部的值在输入完成后不会更改。我猜我完全错了,但似乎无法弄清楚如何使这项工作,也找不到任何这样做的例子。

【问题讨论】:

    标签: c# razor data-binding components blazor


    【解决方案1】:
    @foreach (var propertyInfo in nfo)
    {
        <input type="text" class="form-control"      
        value="@propertyInfo.GetValue(SCustomer)" 
        @onchange="@((ChangeEventArgs __e) =>
           propertyInfo.SetValue(SCustomer, __e.Value.ToString()))" />
    }
    

    【讨论】:

    • 这可能缺少一个结束括号并给出以下错误:“System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'” 值得注意的是客户类的公共道具并不总是类型字符串。 (我会尝试更新问题以便提及)。
    • “文本”类型的输入值始终是一个字符串。切换属性类型并根据类型创建其他类型的输入。
    • 我找到了一种方法,虽然它有点丑,但我自己的回答。谢谢你的帮助!它指导了我很多。另外,如果您在这个问题上有比我更好的工作解决方案,请发布它,我一定会接受它!
    【解决方案2】:
    @foreach(propertyInfo in nfo)
    {
      <label>@propertyInfo.Name</label>
      <input type="text" value="@propertyInfo.GetValue(SCustomer)" @onchange="@((ChangeEventArgs __e) => 
        propertyInfo.SetValue(SCustomer,Convert.ChangeType(__e.Value, 
        propertyInfo.PropertyType,null))"/>
    }
    

    【讨论】:

      【解决方案3】:

      我终于找到了一种方法,这是我的解决方案: 我创建了一个助手类:

      public class PropHolder
          {
              [Parameter]
              public PropertyInfo info { get; set; }
              [Parameter]
              public string type { get; set; }
              public PropHolder(PropertyInfo nfo, string propType)
              {
                  info = nfo;
                  type = propType;
              }
          }
      

      然后我创建了这个类的字典和一些检查函数(这是在 Clogic 内部)

      [Parameter]
              public Dictionary<int, PropHolder> Props{ get; set; }
              public void GetAllProps()
              {
                  Props = new Dictionary<int, PropHolder>();
                  //nfo = SCustomer.GetType().GetProperties();
                  int Cid = 0;
                  foreach (PropertyInfo pif in SCustomer.GetType().GetProperties())
                  {
                      Props[Cid] = new PropHolder(pif, pif.PropertyType.Name);
                      Cid++;
                  }
              }
      
              public string CheckName(PropHolder propertyInfo)
              {
                  if (propertyInfo.GetType() == typeof(PropHolder))
                  {
                      return propertyInfo.type;
                  }
                  else
                  {
                      return propertyInfo.GetType().Name.ToString();
                  }
      
              }
              public PropertyInfo getInfo(PropHolder propertyInfo)
              {
                  if (propertyInfo.GetType() == typeof(PropHolder))
                  {
                      return propertyInfo.info;
                  }
                  else
                  {
                      return null;
                  }
              }
      

      最后我能够遍历我的字典的键并正确绑定所有值(从“来自火星的 agua”给出的答案中得到了很多帮助来解决这个问题) 这是 updateC.razor 内容:

      @if (Props != null)
              {
      
                  @foreach (int key in Props.Keys)
                  {
      
                      var pinfo = Props[key];
                      @if (CheckName(pinfo) == "String")
                      {
                          <input type="text" class="form-control" value=@(getInfo(pinfo).GetValue(SCustomer)) @onchange="@((ChangeEventArgs __e) => getInfo(pinfo).SetValue(SCustomer, __e.Value.ToString()))" />
                      }
                  }
              }
      

      这为每个字符串类型的道具提供了一个输入框,如果要处理其他类型,现在可以轻松添加它。这可能不是最好的解决方案,但它确实有效。如果发布任何更好的工作解决方案,我会更新答案。

      【讨论】:

        【解决方案4】:

        我使用泛型解决了这个问题。这让每个输入类型都传递一个泛型类型,该泛型类型定义了它想要使用的类型。

        <input @bind="Name.Value" />
        <input @bind="Age.Value" />
        
        <div><code>Name</code>: @Name.Value</div>
        <div><code>Age</code>: @Age.Value</div>
        
        @code {
            private FormField<string> Name { get; set; } = new FormField<string>();
            private FormField<int> Age { get; set; } = new FormField<int>();
        
            public class Form
            {
                public ICollection<IFormField> Fields { get; set; }
            }
        
            public interface IFormField
            {
                public int ControlType { get; set; }
            }
        
            public class FormField<T> : IFormField
            {
                public int ControlType { get; set; }
                public T Value { get; set; }
            }
        }
        

        它在 BlazorFiddle 上:https://blazorfiddle.com/s/wen1g26q

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-11-16
          • 1970-01-01
          • 2022-07-05
          • 1970-01-01
          • 2018-07-02
          • 2016-10-11
          • 2013-06-10
          相关资源
          最近更新 更多