[ASP.NET 自訂控制項]DropDownList唯讀時改用TextBox/Label顯示
緣由:
案子上SA希望DropDownList在頁面唯讀時,可以不給User選取,
但是設定Enabled=false,會導致畫面上的<select>字是灰色的,SA希望字不是灰色的,
如果做不到也可以乾脆用textbox或label來顯示唯讀的資訊。
讓該控制項的資訊,如同word的內文呈現,可以跟前後文直接串接在一起。
Enabled設定成false時,Render到頁面上會將disabled屬性設成唯讀。
用了一下CSS去改字體顏色,似乎是沒啥作用。(有其他大大可以提供解法的話,再麻煩指導一下)
CSS這條路try不出來之後,其實有兩種解法,
解法1:利用javascript去記錄目前<Select>的selectedindex,
接著判斷如果<select>.disable=true,就將<select>.disable改成false,
這樣一來,字就不會灰灰的,但是要怎麼控制唯讀呢?
很簡單,把<Select>裡面的items全部remove掉,只保留剛剛選取的item,
只剩下一個item,自然就沒得選了。
解法2:由於對Custom Control還蠻熟的,讓開發成員最無腦的方式,就是直接把DropDownList改掉。
這邊示範的是,覆寫DropDownList的Render()事件,判斷若DropDownList的Enabled為唯讀,則Render成textbox,
自動根據內文的多寡控制textbox的長度。
好處是,仍然保留DropDownList的viewstate,對開發人員來說,它就是一個長的像textbox的DropDownList。對寫server端的CODE來說,完全沒有差異。
甚至還可以讀取到selectedindex和selectedvalue。
程式碼如下:
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Joey
{
public class JoeyDropDownList : DropDownList
{
int _ReadOnlyWidth = 0;
/// <summary>
/// Gets or sets the width of the Readonly.
/// </summary>
/// <value>The width of the readonly.</value>
public int ReadOnlyWidth
{
get { return _ReadOnlyWidth; }
set { _ReadOnlyWidth = value; }
}
protected override void Render(HtmlTextWriter writer)
{
if (this.Enabled)
{ base.Render(writer); }
else
{
if (this.ReadOnlyWidth == 0)
{ this.ReadOnlyWidth = 13; }
int textlength = this.SelectedItem.Text.Length;
writer.AddAttribute("value", this.SelectedItem.Text);
writer.AddAttribute("type", "text");
writer.AddAttribute("readonly", "readonly");
writer.AddAttribute("style", "width:" + Convert.ToString(textlength * this.ReadOnlyWidth) + "px;" + "border:solid 0px;" + "text-align:center;");
writer.RenderBeginTag("input");
writer.RenderEndTag();
}
}
}
}
Sample頁面aspx
<%@ Register Assembly="Joey" Namespace="Joey" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>未命名頁面</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<cc1:joeydropdownlist id="JoeyDropDownList1" runat="server">
<asp:ListItem Value="14">Ace</asp:ListItem>
<asp:ListItem Value="13">King</asp:ListItem>
<asp:ListItem Value="12">Queen</asp:ListItem>
<asp:ListItem Value="11">Jack</asp:ListItem>
<asp:ListItem Value="JoeyTesting">長一點的選項用來測試自動寬度</asp:ListItem>
</cc1:joeydropdownlist>
<asp:Button ID="Button1" runat="server" Text="不唯讀" />
<asp:Button ID="Button2" runat="server" Text="唯讀" />
DropDownlist的值<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
DropDownlist的text<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</div>
</form>
</body>
</html>
Sample頁面aspx.vb
Partial Class TestDropDownList
Inherits System.Web.UI.Page
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.JoeyDropDownList1.Enabled = False
Me.TextBox1.Text = Me.JoeyDropDownList1.SelectedValue
Me.TextBox2.Text = Me.JoeyDropDownList1.SelectedItem.Text
End Sub
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.JoeyDropDownList1.Enabled = True
Me.TextBox1.Text = Me.JoeyDropDownList1.SelectedValue
Me.TextBox2.Text = Me.JoeyDropDownList1.SelectedItem.Text
End Sub
End Class
畫面demo:
1.一開始不唯讀的狀態,選取Queen
2.點了唯讀後,Queen變成文字
3.點了不唯讀後,選”長一點的選項用來測試自動寬度”,來測試中文
4.點了唯讀後,”長一點的選項用來測試自動寬度”變成文字
PS:寬度的部分,額外開了一個屬性給外面設定,若不設定,預設一個字為13px,其實13是給中文字使用,英文數字應該是7px。
想要改良的人可以自行判斷SelectedItem.Text有幾個英文數字,有幾個中文字,再去調整自動寬度。
PS2:請注意最後Render的tag是input,type為text,如果會被CSS或版面影響,請自行調整。(例如擺在最後面會不會長度太長沒自動斷行之類的…)
感謝Williams提供ASP.NET forum上的另外一種解答:http://forums.asp.net/p/1021814/1384091.aspx
forum上的code如果要放在自訂控制項裡面,就是把Render()覆寫成下面的code。
{
if (!this.Enabled)
{
this.Enabled = true;
foreach (ListItem i in this.Items)
{
if (i.Selected != true)
{ i.Enabled = false; }
}
base.Render(writer);
this.Enabled = false;
}
else
{ base.Render(writer); }
}
Source Code下載:(把兩種作法都包進去的class檔): JoeyDropDownList.rar
blog 與課程更新內容,請前往新站位置:http://tdd.best/