【问题标题】:Get Selected Text asp.net custom server control获取选定文本 asp.net 自定义服务器控件
【发布时间】:2012-05-09 05:13:48
【问题描述】:

我需要通过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 代码隐藏

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;
 }

【问题讨论】:

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


    【解决方案1】:

    除非您将更改发布给他,否则服务器不会让您的客户端更改。您的 HtmlAnchors 在 HTML 中呈现为 &lt;a&gt; 控件,这些类型的控件不会向服务器发布任何内容。

    您将需要一个&lt;input&gt; 控件来将更改输入到服务器中(这就是它们被称为输入控件的原因)。我建议使用&lt;input type=hidden&gt; 来保存anchor.innerText 的值并保持其状态。

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

    首先,您需要将您要插入的selectedTextAnchorhiddenField 定义为私有字段。这是因为您需要在 CreateChildControls 方法以及您的 Text 属性的 getter 和 setter 中访问它们。部分设计器类定义您希望在代码隐藏中可用的控件的方式非常相似。

    ServerControl.cs

    private HtmlAnchor selectedTextAnchor;
    private HtmlInputHidden hiddenField;
    

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

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

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

    一旦您执行this.Controls.Add(dummyControl),您就会使 dummyControl 成为页面的一部分,并且其dummyControl.ClientID 将突然更改以反映您将其附加到的页面的层次结构。

    我更改了控件附加到控件集合的顺序,以便我们可以在构建 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 属性的方式。

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

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

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

    SET 属性时,只需将其分配给selectedTextAnchor

    GET 和 SET 中,您需要调用 EnsureChildControls(),它实际上会调用您的 CreateChildControls() 以确保您的 selectedTextAnchorhiddenField 控件在您尝试之前已实例化获取它们的一些属性。与Composite Controls 中的处理方式几乎相同。

    ServerControl.cs

    public string Text
    {
        get
        {
            EnsureChildControls();
            if (this.Page.IsPostBack)
            {
                string HiddenFieldPostedValue = Context.Request.Form[hiddenField.UniqueID];
                // Assign the value recovered from hidden field to the Anchor
                selectedTextAnchor.InnerText = HiddenFieldPostedValue;
                return HiddenFieldPostedValue;
            }
            else
            {
                return selectedTextAnchor.InnerText;
            }
        }
        set
        {
            EnsureChildControls();
            selectedTextAnchor.InnerText = value;
        }
    }
    

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

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

    祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 2011-09-13
      相关资源
      最近更新 更多