2013-05-04 3 views
0

Я создал некоторые пользовательские текстовые поля, которые унаследованы от текстового поля. Для следующего шага я хочу зарегистрировать javascript с помощью обертки.Использование шаблона декоратора для элементов управления asp.net

Декоратор шаблон позволяет мне делать, если только я могу наследовать его из текстового поля и передавать пользовательские текстовые поля в качестве параметра конструктора.

Проблема заключается в том, как я могу использовать конструктор при добавлении элемента управления на страницу aspx или в основном как использовать шаблон декоратора для элементов управления asp.net.

EDIT:

Просто это моя проверка базового класса (Ifield является интерфейсом проверки Это может быть проигнорировано.):

public abstract class ValidationBase : TextBox, IField 
{ 
    private readonly IField _field; 
    protected ValidationBase(IField field) 
    { 
     _field = field; 
    } 

    public int MinLength 
    { 
     get { return _field.MinLength; } 
     set { _field.MinLength = value; } 
    } 

    public bool Required 
    { 
     get { return _field.Required; } 
     set { _field.Required = value; } 
    } 

    // other porperties etc... 

    protected override void OnPreRender(EventArgs e) 
    { 
     // DO SOME STUFF... 

     base.OnPreRender(e); 
    } 
} 

И это мой конкретный класс (EmailField является конкретным осущ. из Ifield игнорировать ...):

public class ValidationEmail : ValidationBase 
{ 
    public ValidationEmail() 
     : base(new EmailField(string.Empty)) 
    { 
    } 
} 

И, наконец, я хочу, чтобы это реализовать (я решился на WordPad это не может быть точно реализ.):

public class JsRegisterDecorator : ValidationBase 
{ 
    private readonly ValidationBase _validationObj; 

    //I am not quite sure about the constructor but i can handle 
    public JsRegisterDecorator(ValidationBase concreteValidationObj) 
     : base(concreteValidationObj) 
    { 
     _validationObj = concreteValidationObj; 
    } 

    //Wrap the properties 

    protected override void OnPreRender(EventArgs e) 
    { 
     //Register JS Files... 
     _validationObj.OnPreRender(e); 
    } 
} 

Проблема в том, что я могу использовать этот декоратор? Поскольку элементы управления asp.net конструкт автоматически: (?, Где можно поставить параметр конструктора)

<vc:ValidationEmail ID="ValidationEmail1" runat="server"/> 

Я не знаю, я могу использовать это:

<vc:JsRegisterDecorator ID="ValidationEmailWithJs1" runat="server"/> 
+0

Не могли бы вы рассказать о своем конкретном сценарии? Что вы хотите достичь с помощью шаблона Decorator, применяемого для контроля, что вы пытались сделать или пытались? –

+0

@AlexanderManekovskiy Спасибо за комментарий. Я обновил свой вопрос. – pilavust

ответ

1

Я решить мою проблему помощи AlexanderManekovskiy по, а также некоторые другие вопросы:

И вот решение:

Я сделал JsRegistererForValidationBase как WebControl и реализован INamingContaier.

Для детей элементы, которые я создал Children Недвижимость, которая принимает olny список Validation Base.

И наконец OnInit метод, я зарегистрировал js.

Вот код:

[ParseChildren(true)] 
[PersistChildren(true)] 
[ToolboxData(@"<{0}:JsRegistererForVB runat=""server""></{0}:JsRegistererForVB>")] 
public class JsRegistererForValidationBase : WebControl, INamingContainer 
{ 
    private ValidationFieldCollection _children; 

    [PersistenceMode(PersistenceMode.InnerProperty)] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
    public ValidationFieldCollection Children 
    { 
     get 
     { 
      if (_children == null) 
       _children = new ValidationFieldCollection(); 
      return _children; 
     } 
    } 

    protected override void CreateChildControls() 
    { 
     Controls.Clear(); 
     foreach (var c in _children) 
      Controls.Add(c); 
    } 

    protected override void OnInit(EventArgs e) 
    { 
     //DO THE REGISTER STUFF 

     base.OnInit(e); 
    } 

    protected override void Render(HtmlTextWriter writer) 
    { 
     RenderChildren(writer); 
    } 
} 

public class ValidationFieldCollection : List<ValidationBase> { } 

}

И на стороне Aspx становится так:

<vc:JsRegisterer ID="JsRegisterer1" runat="server"> 
    <Children> 
     <vc:ValidationEmail ID="ValidationEmail1" runat="server"/> 
     <vc:ValidationEmail ID="ValidationEmail2" runat="server"/>, 
     <!--etc--> 
    </Children> 
</vc:JsRegisterer> 

Для детальной imlementation я добавил код для codeplex

1

Я не думаю, что декоратор припадки Ну вот. В общем, я видел больше приложений Builder и Factory Method для элементов управления ASP.NET.

Чтобы частично решить вашу задачу, вы можете использовать ControlBuilder. Это даст вам возможность изменить тип элемента управления с ValidationBase на JsRegisterDecorator или ValidationEmail. Вам нужно украсить класс с помощью ControlBuilderAttribute, наследовать класс строителя от ControlBuilder и переопределить метод Init.

[ControlBuilder(typeof(ValidationBaseBuilder))] 
public abstract class ValidationBase : TextBox, IField { } 

public class ValidationBaseBuilder: ControlBuilder 
{ 
    public override void Init(TemplateParser parser, ControlBuilder parentBuilder, Type type, string tagName, string id, System.Collections.IDictionary attribs) 
    { 
     var newType = typeof(/*here you can put a JsRegisterDecorator type*/); 
     base.Init(parser, parentBuilder, t, tagName, id, attribs); 
    } 
} 

Но я не уверен в таком подходе. ControlBuilder не может дать вам легкий контроль над конструктором. Конечно, вы можете переопределить ProcessGeneratedCode в ControlBuilder, а Дэвид Эббо стоит blog post, но это было бы непростой задачей переписать конструктор для управления и сделать решение простым.

Как альтернатива, которая будет работать, я могу предложить добавить абстрактный (или виртуальный) метод, например RegisterScripts, внутри ValidationBase и называть его OnPreRender. Каждый элемент управления будет знать, какие сценарии ему нужны, и процесс создания нового элемента управления валидатором будет чистым и простым. Если вы хотите отделить знания JS-скриптов от конкретных реализаций, тогда подходите, как показано в ASP.NET DynamicData (read MetaTable).

Другое дело, что я могу видеть, что ваша идея достаточно близко к DynamicControl и, возможно, можно было бы получить больше идей из ASP.NET DynamicData как Field Templates и IFielTemplateFactory.

+0

Как насчет создания 'WebControl' унаследованного' INamingContainer'? В качестве дочерних элементов он принимает только «ValidationBase» и «OnLoad» регистрирует javascript. – pilavust

+0

@pilavust звучит хорошо, если он вписывается в ваше дело. Другая идея состоит в том, что вы можете создать элемент управления «один на страницу/мастер» 'ValidationScriptManager' (например,« ScriptManager »), в котором будут регистрироваться элементы контроля проверки, которые собирают, объединяют и возвращают необходимые скрипты во время запроса. –

+0

Я согласен с вами. Я очень благодарен за вашу поддержку. Чтобы внести свой вклад в этот вопрос, могу ли я ответить на него своим решением/внедрением? – pilavust

Смежные вопросы