如何为ASP.NET用户控件创建客户端API

How do you create a client-side API for an ASP.NET User Control?

本文关键字:控件 创建 客户端 API 用户 NET ASP      更新时间:2023-09-26

例如:我有一个用户控件,让我们称之为"MyControl1",我想创建"Show()"answers"Hide()"javascript函数,这些函数可以从父页上的javascript调用,比如"MyControl1.Show();"

很明显,页面上可能有多个控件,所以如果您在页面上删除了两个控件:

   <MyTag:MyControl ID="MyControl1" runat="server" />
   <MyTag:MyControl ID="MyControl2" runat="server" />

如果能做这样的事情就太好了:

   function ParentPageJavascriptFunction(){
      MyControl1.Show();
      MyControl2.Hide();
   }

我该怎么做?我找到的每一篇文章都是关于如何在用户控件中挂接事件的,我只希望父页面能够在它认为合适的时候调用某些函数,或者也许有一种方法可以使用事件来做我想做的事情,但我只是不理解

编辑:这似乎没有得到正确的理解,这个怎么样。。。

这就是我假设的控制:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyControl.ascx.cs" Inherits="controls_MyControl" %>
<script type="text/javascript">
    function Display(msg) {
        var Label1ClientID = '<%= Label1.ClientID %>';
        document.getElementById(Label1ClientID)... (display the message)
    } 
</script>
<asp:Label ID="Label1" runat="server"> </asp:Label>

现在,"父"页注册控件如下:

<%@ Register Src="~/controls/MyControl.ascx" TagName="MyControl" TagPrefix="MyTag" %>

在身体里它有这个:

<asp:Button ID="MyButton1" runat="server" Text="Display" OnClientClick="javascript:MyControl1.Display('hello'); return false;" />
    <MyTag:MyControl Id="MyControl1" runat="server">
    </MyTag:MyControl>

显然,唯一的问题是,这不起作用,但这正是我想要解决的问题。你是如何做到这一点的?我希望能够允许用户控件嵌套在其中的页面(父页面)能够调用该用户控件的Display函数。我意识到,你可以只调用Display,因为它只是js(无论它是否在用户控件中),但如果你在该页面上有两个这样的控件,那么你如何创建javascript,使父页面能够区分它想要调用哪个用户控件函数呢?

您尝试做的事情非常简单。asp.net控件是一种将纯html封装到页面控件中的庞大方法。为了能够在控件上调用javascript事件,您必须知道控件呈现到页面的结果的ID。

注意:所有.net控件都有一个名为.ClientID的成员,它表示运行时将生成的内容,作为它设计用于封装/呈现的HTML的ID。

为了在页面上显示控件的ID,您需要执行以下操作:

var dotNetHtmlClientID = '<%= txtMessage.ClientID %>';
$('#' + dotNetHtmlClientID).bind('onclick', function(){
    //dostuff
});

第一行是c#内联代码,用于从运行时获取ClientID。

更新**

如果你想从用户控件所在的页面上获得它的客户端ID,你需要这样做:

//在点网页服务器端

protected string controlClientId;
void Page_Load(object sender, Eventargs e)
{
     controlClientId = Page.FindControl("MyControlThatImBindingEventToDotNetId").ClientID;
}

//在页面客户端

var dotNetHtmlClientID = '<%= controlClientId %>';
$('#' + dotNetHtmlClientID).bind('onclick', function(){
    //dostuff
});

解决这个问题的一种方法是用javascript创建一个模块。简而言之,这意味着您可能拥有xyzClientApi.js,它包含一些增强页面功能的函数集。

在该文件中,您将创建一个对象,该对象引用了您对脚本功能感兴趣的控件。在javascript中,您可以在函数中嵌套变量或对象,以有效地命名它们的名称空间(这将减少javascript与其他可能使用的javascript之间的冲突)。

此函数将为您的客户端api创建一个作用域:

// this is the variable that you'll reference from your view markup
// the style shown here is a self executing anonymous function.
// sounds scarier than it is! don't be afraid.
var xyzClientApi = (function($) {
    // this is the object that will be assigned to xyzClientApi.
    // the {} in this line is just an object initializer
    // you can put things inside of it using this syntax: <name>:<value>
    var model = {};
    // you can use an init() function to accept parameters
    // when you initialize the api.
    // i.e. xyzClientApi.init({myUserControl:'#myUserControl1', myButton:'#myButton1'});
    model.init = function(params) {
        // add properties and functions to your model
        // based on parameters in here
        model.myUserControl = {
          display: function(text) {
              $(params.myUserControl).val(text);
          }
        };
        // assign a click handler to your button!
        $(params.myButton).click(function(){
           model.myUserControl.display('hello!');
        });
    };
    // remember to return model!
    return model;
// by passing jQuery here, the '$' parameter
// is guaranteed to be jQuery when you use it
// this is to play nice with other js libraries
// that might also use '$' at the global scope.
})(jQuery);

然后,你就可以在你的标记中使用这个:

<script type="text/javascript" src="xyzClientApi.js"></script>
<script type="text/javascript">
    // standard jQuery DOM ready function
    $().ready(function(){
        // call the init from above
        // this is using the object initializer syntax in javascript
        // it's just a nice way of grouping your parameters
        // each property of the object is declared, followed by a colon,
        // which is followed by a value. this value can be any valid javascript
        // object, like a string, value, or some other object.
        // in this case, we're passing the known control IDs in.
        xyzClientApi.init({
           myUserControl: '<%= MyUserControlClientID %>',
           myButton: '<%= MyButtonControlClientID %>'
        });
    });
</script>

如果您不知道控件的ID,或者无法合理地确定它是什么,请尝试将其包装在div或其他html元素中:

<div id="MyControlIsInhere">...your control...</div>

然后你可以使用这样的选择器:

'#MyControlIsInHere input[type=button]'

我的解决方案包括在用户控件中添加一个包装器div,然后使用jQuery对其进行扩展-添加您想要的任何客户端方法和属性。诀窍是将包装器div的ID设置为与用户控件的ID相同,使用id='<%= this.ID %>'

用户控件本身实际上并没有呈现任何内容(只有内容),因此div只是为您提供一个对象,该对象的ID可以在包含页面上引用(因为您知道用户控件的ID)。通过在div之外扩展属性/方法,所有内容都有了清晰的范围(全局命名空间中没有任何内容),您可以简单地使用标准$get('myUcWhatever')使用用户控件的ID获取对象引用,这样就可以开始了。

如果你想了解更多细节,我在博客上发布了完整的解释和演示解决方案:http://programmerramblings.blogspot.com/2011/07/clientside-api-for-aspnet-user-controls.html