代码改变世界

带Value属性的扩展CheckBox控件

2006-08-31 12:27  晓风残月  阅读(8116)  评论(7编辑  收藏  举报
ASP.NET 的CheckBox 提供了对 <input type="checkbox" /> 标记 的封装,但是CheckBox没有提供与客户端相对应的 value 属性,而很多时候(不管是server side 或者client side )我们在确定某个CheckBox 被 checked,也需要获取一个对应的 value。
如何解决?其实方法很多。
  1. 为每个CheckBox 提供 HiddenField,将 CheckBox对应的Value存储在HiddenField中
    缺点:麻烦,繁琐。
  2. 为每个CheckBox 提供 ViewState,将 CheckBox对应的Value存储在ViewState中
    缺点:无法在client side 读取。
  3. 换用CheckBoxList,因为 CheckBoxList 实现了 ListControl,同时具有Text和Value属性
    缺点:单个CheckBox不合适。适合于多个CheckBox的组合。
    knonwn bug: CheckBoxlist 内部使用的 ListITem.Attributes 为实现视图(ViewState) updated: @07-05-13
  4. 换用Html服务器控件:<input runat="server" type="checkbox" />
    缺点:没有了Text属性,如果需要需要自行添加。
  5. 开发自己的扩展CheckBox,使之具有Value属性,并对<input type="checkbox"  valu="somevlaue" />对应。
  6. more unknown solutions。^_^

下面就是一个扩展的CheckBox:

[DefaultProperty("Text")]
    [ToolboxData(
"<{0}:XCheckBox runat=\"server\" />")]
    
public class XCheckBox : CheckBox
    
{
        [Bindable(
true)]
        [Category(
"Appearance")]
        [DefaultValue(
"")]
        [Localizable(
true)]
        
public string Value
        
{
            
get
            
{
                String s 
= (String)ViewState["Value"];
                    // updated @07-05-13
                     return String.IsNullOrEmpty(s) ? "on" : s;
                //
return ((s == null? String.Empty : s);
            }

            
set
            
{
                
// 将值存储在 ViewState 中
                ViewState["Value"= value;
            }

        }


        
protected override void RenderContents(HtmlTextWriter output)
        
{
            
base.RenderContents(output);
        }


        
protected override void AddAttributesToRender(HtmlTextWriter writer)
        
{
            
// 添加 value 属性标记(在客户端呈现),并设置对应 Value属性值(服务器端)
            writer.AddAttribute(HtmlTextWriterAttribute.Value, Value);
            
base.AddAttributesToRender(writer);
        }

    }

下面是改控件呈现的HTML:
<input value="valueOfXCheckBox1" id="XCheckBox1" type="checkbox" name="XCheckBox1" /><label for="XCheckBox1">textOfXCheckBox1</label>

需要注意的是:
如果在 Value 属性的 set 访问器中这样设置:
this.Attributes["value"= value;
asp。net引擎不会在客户端呈现 value属性标记,因此不会得到预期的效果
但是如果设置其他属性却是可以的:
this.Attributes["onclick"= "alert(this.id)";

anybody knows why?

updated:2007年5月13日
发现了一个bug,当你将checkbox的value设置成空字符串的时候,如,
checkbox1.Attributes["value"] = "";
那么当页面回发(PostBock)的时候服务端无法真正获取此checkbox.checked 属性,此时永远返回页面初次请求的checkbox1.checked值,
后来才明白,原来html form中对于 <input type=checkbox>的value属性 具有默认值:on,如果这样设置<input type="checkbox" value="" />,那么表单回发是不会包含此 checkbox的,服务器自然也得不到这个值(asp.net 中通过 Request.Form 集合获取)
因此,应该如此修改 XCheckBox.Value 实现:

[Bindable(true)]
        [Category(
"Appearance")]
        [DefaultValue(
"")]
        [Localizable(
true)]
        
public string Value
        
{
            
get
            
{
                String s = (String)ViewState["Value"];
                return String.IsNullOrEmpty(s) ? "on" : s;
            }
            
set
            
{                
                ViewState[
"Value"= value;             
            }

        }

update 2008年7月17日
在 ASP.NET 2.0 中为 CheckBox 增加了两个属性分别是 InputAttributes 与 LabelAttributes 来扩展 CheckBox 未能对应到 html checkbox 的属性

<asp:CheckBox ID="CheckBox3" runat="server" Text="Item3" />

CheckBox3.InputAttributes.Add(
"value""3"); // value=3
        CheckBox3.LabelAttributes.CssStyle.Add(HtmlTextWriterStyle.Color, "red"); // 文本显示为红色


输出结果:
<input id="CheckBox3" type="checkbox" name="CheckBox3" value="3" /><label for="CheckBox3" style="color:red;">Item3</label>
 

有点遗憾的是,依然无法以声明的方式直接在 .aspx 中设置 value 值。

另外 RadioButton 继承自 CheckBox,自然也就支持上述两个新增属性。