【问题标题】:How to get value from System.Web.UI.Control (base class)?如何从 System.Web.UI.Control(基类)中获取价值?
【发布时间】:2013-02-19 15:19:31
【问题描述】:

有没有办法使用基类访问控件的值/文本?

查看TextBoxHiddenField,System.Web.UI.Control 是它们共享的最具体的基类。似乎是一个不错的候选人,但我看不到访问文本/值的明显方法。

我确实看到两个类定义都使用 ControlValuePropertyAttribute 来识别保存其文本/值的属性...例如HiddenField 设置为“Value”,TextBox 设置为“Text”。不过,不确定如何使用该信息来检索数据。

背景

我有一个扩展方法,它获取一些 Web 控件(例如 TextBox)的文本并将其转换为给定类型:

<Extension()> _
Public Function GetTextValue(Of resultType)(ByVal textControl As ITextControl, ByVal defaultValue As resultType) As resultType
    Return ConvertValue(Of resultType)(textControl .Text, defaultValue)
End Function

现在,我需要一个 HiddenField 的值(它没有实现 ITextControl 接口)。重载函数很容易,但只处理基类而不必再处理编写重载就很棒了。

编辑 - 附加信息

这是一个如何使用扩展方法的例子

Dim myThing as Decimal = tbSomeWebControl.GetTextValue(Of Decimal)(0)  ' Converts the textbox data to a decimal
Dim yourThang as Date = hdnSomeSecret.GetTextValue(Of Date)(Date.MinValue)  ' Converts the hiddenfield data to a Date

目前,这需要两个重载,因为使用隐藏字段中的 Value 属性和文本框中的 Text 属性访问数据。

重载有什么问题?什么都没有,除了我一遍又一遍地编写几乎相同的代码(只是修改定义的第一个参数和它的调用的第一个参数)。

【问题讨论】:

    标签: asp.net web-controls asp.net-webcontrol


    【解决方案1】:

    您不能使用面向对象的方法来获取值,因为它们在您可以从中获取数据的继承树中没有共同的祖先。解决方案太不优雅了,您应该只传递WebControl 并动态检查类型。

    请原谅我的 C#:

    (请注意,这是记事本代码,我没有运行任何代码,因此您可能需要一些调整)


    解决方案 1:直接从 Request 中获取数据

    缺点:不是很像 ASP.NET。但是可以完成这项工作。

    public string GetTextValue<ResultType>(WebControl control, ResultType defaultValue)
    {
        // If you only wish data from form, and not questy string or cookies
        // use Request.Form[control.UniqueId] instead
        string value = Request[control.UniqueId];
        return ConvertValue<ResultType>(value, defaultValue);
    }
    

    解决方案 2:动态检查类型

    缺点:您必须为多种控件类型提供处理

    public string GetTextValue<ResultType>(WebControl control, ResultType defaultValue)
    {
        if (control is ITextControl)
            return ConvertValue<ResultType>((ITextControl)control.Text, defaultValue);
        else if (control is HiddenField)
            return ConvertValue<ResultType>((HiddenField)control.Value, defaultValue);
        else if (anothertype)
            return ConvertValue<ResultType>(another_retrieval_method, defaultValue);
    }
    

    解决方案 3:使用反射

    缺点:反射可能很棘手,看起来不优雅,并且在许多调用中可能很慢

    public string GetTextValue<ResultType>(WebControl control, ResultType defaultValue)
    {
        // Get actual control type
        Type controlType = control.GetType();
        // Get the attribute which gives away value property
        Attribute attr = controlType.GetCustomAttribute<ControlValuePropertyAttribute>();
        if (attr == null)
            throw new InvalidOperationException("Control must be decorated with ControlValuePropertyAttribute");
        ControlValuePropertyAttribute valueAttr = (ControlValuePropertyAttribute)attr;
        // Get property name holding the value
        string propertyName = valueAttr.Name;
        // Get PropertyInfo describing the property
        PropertyInfo propertyInfo = controlType.GetProperty(propertyName);
        // Get actual value from the control object
        object val = propertyInfo.GetValue(control);
        if (val == null)
            val = "";
    
        return ConvertValue<ResultType>(val, defaultValue);
    }
    

    【讨论】:

      【解决方案2】:

      我认为DataItemContainer 将是您正在寻找的最接近的东西。

      【讨论】:

      • 它看起来不像 Label 或 HiddenField 实现 IDataItemContainer。他们有这个属性,但实例返回 null/Nothing 为 myControl.DataItemContainer
      • 也许更好的解决方案似乎是为您需要使用它的特定控件创建多个扩展方法,尽管我并不完全了解您具体要做什么。
      • 目前我有多种扩展方法,通用逻辑在它自己的函数ConvertValue中。只是在寻找一种方法来整合特定于控件的方法(不是真正的问题,只是更少的代码 == 更好)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      • 2017-10-01
      • 2018-04-07
      • 2021-12-26
      • 1970-01-01
      • 2016-08-24
      相关资源
      最近更新 更多