【问题标题】:Passing int array as parameter in web user control在 Web 用户控件中将 int 数组作为参数传递
【发布时间】:2008-09-22 19:02:36
【问题描述】:

我有一个 int 数组作为 Web 用户控件的属性。如果可能的话,我想使用以下语法将该属性设置为内联:

<uc1:mycontrol runat="server" myintarray="1,2,3" />

这将在运行时失败,因为它需要一个实际的 int 数组,但正在传递一个字符串。我可以将myintarray 设为字符串并在setter 中解析它,但我想知道是否有更优雅的解决方案。

【问题讨论】:

    标签: asp.net web-user-controls


    【解决方案1】:

    实现一个类型转换器,这是一个,警告:quick&dirty,不用于生产等:

    public class IntArrayConverter : System.ComponentModel.TypeConverter
    {
        public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }
        public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            string val = value as string;
            string[] vals = val.Split(',');
            System.Collections.Generic.List<int> ints = new System.Collections.Generic.List<int>();
            foreach (string s in vals)
                ints.Add(Convert.ToInt32(s));
            return ints.ToArray();
        }
    }
    

    并标记您的控件的属性:

    private int[] ints;
    [TypeConverter(typeof(IntsConverter))]
    public int[] Ints
    {
        get { return this.ints; }
        set { this.ints = value; }
    }
    

    【讨论】:

    • 我在下面添加了一个可以编译的示例。谢谢!
    【解决方案2】:

    @mathieu,非常感谢您的代码。为了编译,我对其进行了一些修改:

    public class IntArrayConverter : System.ComponentModel.TypeConverter
    {
        public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }
        public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            string val = value as string;
            string[] vals = val.Split(',');
            System.Collections.Generic.List<int> ints = new System.Collections.Generic.List<int>();
            foreach (string s in vals)
                ints.Add(Convert.ToInt32(s));
            return ints.ToArray();
        }
    }
    

    【讨论】:

    • 我修复了原来的答案,你可以删除这个如果你想
    【解决方案3】:

    在我看来,合乎逻辑且更可扩展的方法是从asp: 列表控件中获取页面:

    <uc1:mycontrol runat="server">
        <uc1:myintparam>1</uc1:myintparam>
        <uc1:myintparam>2</uc1:myintparam>
        <uc1:myintparam>3</uc1:myintparam>
    </uc1:mycontrol>
    

    【讨论】:

    • 谢谢。这可能有效,但前面有很多额外的代码。我尽量保持简约。
    【解决方案4】:

    伟大的 sn-p @mathieu。我需要使用它来转换 long,但我没有制作 LongArrayConverter,而是编写了一个使用泛型的版本。

    public class ArrayConverter<T> : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }
    
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            string val = value as string;
            if (string.IsNullOrEmpty(val))
                return new T[0];
    
            string[] vals = val.Split(',');
            List<T> items = new List<T>();
            Type type = typeof(T);
            foreach (string s in vals)
            {
                T item = (T)Convert.ChangeType(s, type);
                items.Add(item);
            }
            return items.ToArray();
        }
    }
    

    此版本适用于任何可从字符串转换的类型。

    [TypeConverter(typeof(ArrayConverter<int>))]
    public int[] Ints { get; set; }
    
    [TypeConverter(typeof(ArrayConverter<long>))]
    public long[] Longs { get; set; }
    
    [TypeConverter(typeof(ArrayConverter<DateTime))]
    public DateTime[] DateTimes { get; set; }
    

    【讨论】:

      【解决方案5】:

      您是否尝试过研究类型转换器?这个页面看起来值得一看:http://www.codeguru.com/columns/VB/article.php/c6529/

      此外,Spring.Net 似乎有一个 StringArrayConverter(http://www.springframework.net/doc-latest/reference/html/objects-misc.html - 第 6.4 节),如果您可以通过使用 TypeConverter 属性装饰属性将其提供给 ASP.net,那么它可能会起作用..

      【讨论】:

        【解决方案6】:

        你也可以这样做:

        namespace InternalArray
        {
            /// <summary>
            /// Item for setting value specifically
            /// </summary>
        
            public class ArrayItem
            {
                public int Value { get; set; }
            }
        
            public class CustomUserControl : UserControl
            {
        
                private List<int> Ints {get {return this.ItemsToList();}
                /// <summary>
                /// set our values explicitly
                /// </summary>
                [PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(List<ArrayItem>))]
                public List<ArrayItem> Values { get; set; }
        
                /// <summary>
                /// Converts our ArrayItem into a List<int> 
                /// </summary>
                /// <returns></returns>
                private List<int> ItemsToList()
                {
                    return (from q in this.Values
                            select q.Value).ToList<int>();
                }
            }
        }
        

        这将导致:

        <xx:CustomUserControl  runat="server">
          <Values>
                    <xx:ArrayItem Value="1" />
          </Values>
        </xx:CustomUserControl>
        

        【讨论】:

          【解决方案7】:

          要添加构成列表的子元素,您需要以某种方式设置控件:

          [ParseChildren(true, "Actions")]
          [PersistChildren(false)]
          [ToolboxData("<{0}:PageActionManager runat=\"server\" ></PageActionManager>")]
          [NonVisualControl]
          public class PageActionManager : Control
          {
          

          上面的 Actions 是子元素所在的 cproperty 的名称。我使用 ArrayList,因为我没有用它测试任何其他东西。:

                  private ArrayList _actions = new ArrayList();
              public ArrayList Actions
              {
                  get
                  {
                      return _actions;
                  }
              }
          

          当您的 contorl 初始化时,它将具有子元素的值。那些你可以制作一个只包含整数的迷你类。

          【讨论】:

            【解决方案8】:

            做比尔所说的,你只需要在你的用户控件上创建一个 List 属性。然后你可以按照 Bill 的描述来实现它。

            【讨论】:

              【解决方案9】:

              您可以在 aspx 中添加页面事件,如下所示:

              <script runat="server">
              protected void Page_Load(object sender, EventArgs e)
              {
                  YourUserControlID.myintarray = new Int32[] { 1, 2, 3 };
              }
              </script>
              

              【讨论】:

                【解决方案10】:

                您可以实现一个类型转换器类,在 int 数组和字符串数据类型之间进行转换。 然后使用 TypeConverterAttribute 装饰您的 int 数组属性,指定您实现的类。然后,Visual Studio 将使用您的类型转换器对您的属性进行类型转换。

                【讨论】:

                  【解决方案11】:

                  如果您在其中一个父控件上使用 DataBinding,则可以使用 DataBinding 表达式:

                  <uc1:mycontrol runat="server" myintarray="<%# new [] {1, 2, 3} %>" />
                  

                  使用自定义表达式生成器,您可以执行类似的操作。表达式生成器:

                  [ExpressionPrefix("Code")]
                  public class CodeExpressionBuilder : ExpressionBuilder
                  {
                      public override CodeExpression GetCodeExpression(System.Web.UI.BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
                      {
                          return new CodeSnippetExpression(entry.Expression.Trim());
                      }
                  }
                  

                  用法:

                  <uc1:mycontrol runat="server" myintarray="<%$ Code: new [] {1, 2, 3} %>" />
                  

                  【讨论】:

                    猜你喜欢
                    • 2010-09-20
                    • 2014-03-25
                    • 2020-04-04
                    • 1970-01-01
                    • 2019-04-20
                    • 2018-07-26
                    • 2010-12-15
                    • 2021-12-14
                    • 1970-01-01
                    相关资源
                    最近更新 更多