Как создать клиентский API для пользовательского элемента управления ASP.NET? - PullRequest
3 голосов
/ 23 июня 2011

Например: у меня есть пользовательский элемент управления, давайте назовем его «MyControl1» и я хочу создать функции JavaScript «Show ()» и «Hide ()», которые можно вызывать из javascript на родительской странице - что-то вроде « MyControl1.Show (); "

Очевидно, что на странице может быть несколько элементов управления, поэтому, если вы отбросили 2 элемента управления на странице:

   <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, потому что это просто js (независимо от того, находится ли он в пользовательском элементе управления или нет), но если у вас есть 2 из этих элементов управления на этой странице, которые не будут работать, так как же вы создаете javascript, чтобы родитель страница может различать, какую функцию пользовательских элементов управления она хочет вызвать?

Ответы [ 3 ]

2 голосов
/ 23 июня 2011

То, что вы пытаетесь сделать, довольно просто. Элементы управления asp.net - это громоздкий способ упаковки чистого HTML в элементы управления на странице. Чтобы иметь возможность вызывать событие javascript для элемента управления, вы должны знать идентификатор результата рендеринга элемента управления на страницу.

ПРИМЕЧАНИЕ: все элементы управления .net имеют член с именем .ClientID, и это представляет то, что среда выполнения сгенерирует как идентификатор HTML, который он предназначен для инкапсуляции / рендеринга.

Чтобы получить идентификатор элемента управления на странице, когда он отображается, вам нужно сделать что-то вроде этого:

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

    //dostuff

});

Первая строка - встроенный код c # для получения ClientID из среды выполнения.

Обновление **

Если вы хотите получить clientID пользовательского элемента управления со страницы, на которой он находится, вам нужно сделать это:

// на стороне сервера с точечной сетью

protected string controlClientId;

void Page_Load(object sender, Eventargs e)
{

     controlClientId = Page.FindControl("MyControlThatImBindingEventToDotNetId").ClientID;

}

// на странице клиента

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

    //dostuff

});
1 голос
/ 01 августа 2011

Мое решение заключается в том, что вы добавляете div-обертку в свой пользовательский элемент управления, а затем используете jQuery для его расширения - добавляя любые клиентские методы и свойства, которые вы пожелаете. Хитрость заключается в том, чтобы установить идентификатор div-оболочки, чтобы он совпадал с пользовательским элементом управления, например id='<%= this.ID %>'.

Пользовательский элемент управления на самом деле ничего не отображает (только содержимое), поэтому div просто дает вам объект с идентификатором, на который вы можете сослаться обратно на вашей содержащей странице (потому что вы знаете идентификатор элемента управления там). А с вашими свойствами / методами, расширенными от div, все аккуратно ограничено (ничего в глобальном пространстве имен), и вы можете просто получить ссылку на объект, используя идентификатор пользовательского элемента управления со стандартным $get('myUcWhatever') - и все готово.

У меня есть полное объяснение и демонстрационное решение, размещенное на моем блоге, если вы хотите больше подробностей: http://programmerramblings.blogspot.com/2011/07/clientside-api-for-aspnet-user-controls.html

1 голос
/ 23 июня 2011

Одним из способов решения этой проблемы является создание модуля в 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);

Тогда вы сможете использовать это в своей разметке:

* * 1010

Если вы не знаете идентификатор своего элемента управления или не можете разумно определить, каким он будет, попробуйте обернуть его в div или какой-либо другой элемент html:

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

Тогда вы бы использовали селектор вот так:

'#MyControlIsInHere input[type=button]'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...