2010-06-29 11 views

Respuesta

6

ACTUALIZACIÓN Esto es ahora un ejemplo completamente funcional. Hay algunas cosas que suceden aquí:

  1. Utilice la devolución de llamada de un control de sustitución para generar la salida del control de usuario que necesita.
  2. Utilice una clase de página personalizada que anule el VerifyRenderingInServerForm y EnableEventValidation para cargar el control y evitar que se generen errores cuando usercontrol contiene controles de servidor que requieren una etiqueta de formulario o validación de evento.

Aquí está el marcado:

<asp:Substitution runat="server" methodname="GetCustomersByCountry" /> 

Aquí está la devolución de llamada

public string GetCustomersByCountry(string country) 
{ 
    CustomerCollection customers = DataContext.GetCustomersByCountry(country); 

    if (customers.Count > 0) 
     //RenderView returns the rendered HTML in the context of the callback 
     return ViewManager.RenderView("customers.ascx", customers); 
    else 
     return ViewManager.RenderView("nocustomersfound.ascx"); 
} 

Aquí está la clase de ayuda para hacer que el control de usuario

public class ViewManager 
{ 
    private class PageForRenderingUserControl : Page 
    { 
     public override void VerifyRenderingInServerForm(Control control) 
     { /* Do nothing */ } 

     public override bool EnableEventValidation 
     { 
      get { return false; } 
      set { /* Do nothing */} 
     } 
    } 

    public static string RenderView(string path, object data) 
    { 
     PageForRenderingUserControl pageHolder = new PageForUserControlRendering(); 
     UserControl viewControl = (UserControl) pageHolder.LoadControl(path); 

     if (data != null) 
     { 
      Type viewControlType = viewControl.GetType(); 
      FieldInfo field = viewControlType.GetField("Data"); 
      if (field != null) 
      { 
       field.SetValue(viewControl, data); 
      } 
      else 
      { 
       throw new Exception("ViewFile: " + path + "has no data property"); 
      } 
     } 

     pageHolder.Controls.Add(viewControl); 
     StringWriter result = new StringWriter(); 
     HttpContext.Current.Server.Execute(pageHolder, result, false); 
     return result.ToString(); 
    } 
} 

Ver estas preguntas relacionadas:

+0

awesome! gracias – mohamadreza

+0

-1 Fuente de referencia: http://weblogs.asp.net/scottgu/archive/2006/10/22/Tip_2F00_Trick_3A00_-Cool-UI-Templalating-Technique-to-use-with-ASP.NET-AJAX-for -non_2D00_UpdatePanel-scenarios.aspx –

-1

estoy bastante seguro de que no puede hacer esto - el control de sustitución se solamente permitirá insertar una cadena en una página outputcached.
Esto tiene sentido si piensa en la salida completa de un control de servidor, que podría ser un <table> que interrumpe todo el marcado cuidadosamente creado y/o algo que requiera una carga de <script> inyectado en la página, mientras inyecta un único la cadena es algo relativamente sencillo.

0

Una cosa Micah 's respuesta deja fuera es que la función de sustitución debe ser static, aceptar un parámetro HttpContext, y devolver una string. Ver this msdn page para más información.

También he extendido la clase de ayuda de Micah para ser un poco más flexible.

de marcado de

<asp:Substitution ID="Substitution1" MethodName="myFunction" runat="server" /> 

Implemenation

public static string myFunction(HttpContext httpContext){ 
    ViewManager vm = new ViewManager(); 

    //example using a Button control 

    Button b = new Button(); 
    b.Text = "click me"; //we can set properties like this 

    //we can also set properties with a Dictionary Collection 
    Dictionary<string,object> data = new Dictionary<string,object>(); 
    data.add("Visible",true); 

    String s = vm.RenderView(b,data); //don't do anything (just for example) 

    //we can also use this class for UserControls 
    UserControl myControl = vm.GetUserControl("~mypath"); 

    data.clear(); 
    data.add("myProp","some value"); 

    return vm.RenderView(myControl,data); //return for Substitution control 
} 

Clase

using System.IO; 
using System.ComponentModel; 
public class ViewManager 
{ 
    private PageForRenderingUserControl pageHolder; 
    public ViewManager() 
    { 
     pageHolder = new PageForRenderingUserControl(); 
    } 

    public UserControl GetUserControl(string path) 
    { 
     return (UserControl)pageHolder.LoadControl(path); 
    } 

    public string RenderView(Control viewControl, Dictionary<string, object> data) 
    { 
     pageHolder.Controls.Clear(); 
     //Dim viewControl As UserControl = DirectCast(pageHolder.LoadControl(Path), UserControl) 

     if (data != null) { 
      Type viewControlType = viewControl.GetType(); 


      dynamic properties = TypeDescriptor.GetProperties(viewControl); 

      foreach (string x in data.Keys) { 
       if ((properties.Item(x) != null)) { 
        properties.Item(x).SetValue(viewControl, data[x]); 
       } 
      } 
     } 

     pageHolder.Controls.Add(viewControl); 
     StringWriter result = new StringWriter(); 
     HttpContext.Current.Server.Execute(pageHolder, result, false); 
     return result.ToString(); 
    } 

    private class PageForRenderingUserControl : Page 
    { 
     public override void VerifyRenderingInServerForm(Control control) 
     { 
      // Do nothing 
     } 

     public override bool EnableEventValidation { 
      get { return false; } 
      // Do nothing 
      set { } 
     } 
    } 

} 

Gracias de nuevo a Micah para el código

Cuestiones relacionadas