获取所选文本asp.net自定义服务器控件

时间:2012-04-28 21:50:49

标签: asp.net custom-controls custom-server-controls servercontrols asp.net-customcontrol

我需要通过javascript获取自定义控件中的最新文本集。当我试图从服务器控件获取所选文本时,它总是返回默认文本&不是修改过的文字。如何保留servercontrol中javascript设置的最新值?以下是供您参考的完整代码..

ServerControl1.cs

[assembly: WebResource("ServerControl1.Scripts.JScript1.js", "text/javascript")]
namespace ServerControl1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
public class ServerControl1 : WebControl
{
    public List<string> ListItems
    {
        get
        {
            return ViewState["items"] as List<string>;
        }
        set
        {
            ViewState["items"] = value;
        }
    }

    public string Text
    {
        get
        {
            return (FindControl("middleDiv").FindControl("anchorID") as HtmlAnchor).InnerText;
        }
        set
        {
            ((FindControl("middleDiv").FindControl("anchorID") as HtmlAnchor)).InnerText = value;
        }
    }

    protected override void CreateChildControls()
    {
        base.CreateChildControls();

        HtmlGenericControl selectedTextContainer = new HtmlGenericControl("div");
        selectedTextContainer.ClientIDMode = System.Web.UI.ClientIDMode.Static;
        selectedTextContainer.ID = "middleDiv";

        HtmlAnchor selectedTextAnchor = new HtmlAnchor();
        selectedTextAnchor.ClientIDMode = System.Web.UI.ClientIDMode.Static;
        selectedTextAnchor.ID = "anchorID";
        selectedTextAnchor.HRef = "";
        selectedTextContainer.Controls.Add(selectedTextAnchor);

        HtmlGenericControl unList = new HtmlGenericControl("ul");

        foreach (string item in ListItems)
        {
            HtmlGenericControl li = new HtmlGenericControl("li");
            HtmlAnchor anchor = new HtmlAnchor();
            anchor.HRef = "";
            anchor.Attributes.Add("onclick", "updateData()");
            anchor.InnerText = item;
            li.Controls.Add(anchor);
            unList.Controls.Add(li);
        }

        selectedTextContainer.Controls.Add(unList);
        Controls.Add(selectedTextContainer);

        ChildControlsCreated = true; 
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        string resourceName = "ServerControl1.Scripts.JScript1.js";

        ClientScriptManager cs = this.Page.ClientScript;
        cs.RegisterClientScriptResource(typeof(ServerControl1), resourceName);
    }
 }
}

JScript1.js

function updateData() {
var evt = window.event || arguments.callee.caller.arguments[0];
var target = evt.target || evt.srcElement;
var anchor = document.getElementById("anchorID");
anchor.innerText = target.innerText;
return false;
}

TestPage Codebehind

protected void Page_Load(object sender, EventArgs e)
{
  if (!Page.IsPostBack)
  {
     List<string> items = GetDataSource();
     ServerControl1.ListItems = items;
     ServerControl1.Text = "Select ..";
  }
}
protected void ClientButton_Click(object sender, EventArgs e)
{
   string selectedText = ServerControl1.Text;
 }

1 个答案:

答案 0 :(得分:2)

除非您将更改发布给他,否则服务器将无法更改客户端。您的HtmlAnchors将以HTML格式呈现为<a>控件,这些类型的控件不会向服务器发送任何内容。

您需要一个<input>控件来将更改输入到服务器中(这就是为什么它们之后被称为输入控件)。我建议<input type=hidden>保持anchor.innerText的值并保持其状态。

您的Javascript函数需要进行修改,以便更新anchor.innerText并更新隐藏的输入值。这样,当页面回发到服务器时,您可以从隐藏字段中检索更新的和客户端修改的值。

首先,您需要将selectedTextAnchor和要插入的hiddenField定义为私有字段。这是因为您需要在CreateChildControls方法以及yout Text属性的getter和setter中访问它们。部分设计器类在很大程度上定义了您希望在代码隐藏中可用的控件。

<强> ServerControl.cs

private HtmlAnchor selectedTextAnchor;
private HtmlInputHidden hiddenField;

在CreateChildControls方法中,您需要插入隐藏字段。

您会注意到我删除了ClientIDMode.Static的使用。使用该模式会使您的客户端控件具有相同的固定ID,并且当您在页面中有多个ServerControl副本时,Javascript可能会混淆,从而失去自定义控件的可重用目的。

相反,您需要为您的Javascript函数提供需要修改的控件的ClientID。 此处的关键是,在尝试获取其ClientID之前,需要将控件附加到Control的层次结构。

只要你做this.Controls.Add(dummyControl),你就会让dummyControl成为Page的一部分,它的dummyControl.ClientID会突然改变,以反映你将它附加到的页面的层次结构

我更改了控件附加到Control集合的顺序,因此我们可以在构建onclick属性时获取其ClientID并传递参数,以便您的Javascript函数知道要影响哪个锚点和hiddenField。

<强> ServerControl.cs

protected override void CreateChildControls()
{
    base.CreateChildControls();

    // Instantiate the hidden input field to include
    hiddenField = new HtmlInputHidden();
    hiddenField.ID = "ANCHORSTATE";

    // Insert the hiddenfield into the Control's Collection hierarchy
    // to ensure that hiddenField.ClientID contains all parent's NamingContainers
    Controls.Add(hiddenField);

    HtmlGenericControl selectedTextContainer = new HtmlGenericControl("div");
    // REMOVED: selectedTextContainer.ClientIDMode = System.Web.UI.ClientIDMode.Static;
    selectedTextContainer.ID = "middleDiv";

    selectedTextAnchor = new HtmlAnchor();
    // REMOVED: selectedTextAnchor.ClientIDMode = System.Web.UI.ClientIDMode.Static;
    selectedTextAnchor.ID = "anchorID";
    selectedTextAnchor.HRef = "";
    selectedTextContainer.Controls.Add(selectedTextAnchor);

    // Insert the selectedTextContainer (and its already attached selectedTextAnchor child) 
    // into the Control's Collection hierarchy
    // to ensure that selectedTextAnchor.ClientID contains all parent's NamingContainers
    Controls.Add(selectedTextContainer);

    HtmlGenericControl unList = new HtmlGenericControl("ul");

    foreach (string item in ListItems)
    {
        HtmlGenericControl li = new HtmlGenericControl("li");
        HtmlAnchor anchor = new HtmlAnchor();
        anchor.HRef = "";

        // The updateData function is provided with parameters that will help
        // to know who's triggering and to find the anchor and the hidden field.
        // ClientID's are now all set and resolved at this point.
        anchor.Attributes.Add("onclick", "updateData(this, '" + selectedTextAnchor.ClientID + "', '" + hiddenField.ClientID + "')");
        anchor.InnerText = item;
        li.Controls.Add(anchor);
        unList.Controls.Add(li);
    }

    selectedTextContainer.Controls.Add(unList);
}

请注意在updateData函数中使用关键字this,它将帮助我们获取触发操作的对象。另请注意,两个Id都作为字符串传递(带单引号)

需要修改Javascript函数,以便更新锚点和隐藏的输入字段。

JScript1.js

    function updateData(sender, anchorId, hidFieldId) {
            // Update the anchor
            var anchor = document.getElementById(anchorId);
            anchor.innerText = sender.innerText;
            // Update the hidden Input Field
            var hidField = document.getElementById(hidFieldId);
            hidField.value = sender.innerText;
            return false;
        }

最后要做的是更改设置和获取Text属性的方式。

当您获取该属性时,您需要检查它是否为回发,如果是,则您要检查来自浏览器的所有信息中是否有您的HiddenInputField。您可以在Request对象中获取来自客户端的所有信息,更具体地说,可以在Request.Form中获取。

Request.Form.AllKeys

页面上所有已启用的输入控件都将成为Request.Form集合的一部分,您可以使用Request.Form[anyInputControl.UniqueID]获取其值。请注意,用于此对象的密钥是UniqueID,而不是ClientID。

从隐藏的输入中获取客户端修改后的值后,将其值分配给selectedTextAnchor,否则它将返回原始的“选择...”文本。

当您设置该属性时,您只需将其分配给selectedTextAnchor

GET和SET 中,您需要拨打EnsureChildControls(),这实际上会调用CreateChildControls()以确保您的selectedTextAnchor和{{1}在尝试获取某些属性之前,会实例化控件。与在Composite Controls中完成的方式非常相似。

<强> ServerControl.cs

hiddenField

这样您就可以拥有一个控件来识别客户端所做的更改。请记住,除非您发现他,否则服务器不会知道客户端的任何变化。

另一种方法是每次通过ajax请求单击链接时都会注意到服务器,但这需要一个全新的不同代码。

祝你好运!