A Generic ViewManager Helper Class

 Hi All,

 Following on from something I saw from Scott Guthrie, a ViewManager which allows you to render a usercontrol and return the generated HTML. I decided to implement a more generic approach which allowed you to set any properties of your custom usercontrol and then render it. So you would use it like so:

//Init the viewmanager
ViewManager<WebUserControl1> man = new ViewManager<WebUserControl1>("~/WebUserControl1.ascx");

We now have access to the control the manager is rendering through the Control property and can set its properties directly like so:

man.Control.Name = "bob";
man.Control.AnotherProperty = "test";


Then finally you call the render method on you viewmanager to get the generated HTML:

Response.Write(man.Render());



Basically the same thing that Scott has done but a little more generic and allows you to set any property of the control you need to render. The code for the ViewManager is below:

public class ViewManager<T> where T : Control {

        #region Properties

        private T _control = default(T);

        /// <summary>
        /// Gives you access to the control you are rendering allows
        /// you to set custom properties etc.
        /// </summary>
        public T Control {
            get {
                return _control;
            }
        }

        // Used as a placeholder page to render the control on.
        private Page _holder = null;

        #endregion    

        #region Constructor

        /// <summary>
        /// Default constructor for this view manager, pass in the path for the control
        /// that this view manager is render.
        /// </summary>
        /// <param name="inPath"></param>
        public ViewManager(string inPath) {
            //Init the holder page
            _holder = new Page();

            // Create an instance of our control
            _control = (T)_holder.LoadControl(inPath);

            // Add it to our holder page.
            _holder.Controls.Add(_control);
        }

        #endregion

        #region Rendering

        /// <summary>
        /// Renders the current control.
        /// </summary>
        /// <returns></returns>
        public string Render() {           
            StringWriter sw = new StringWriter();

            // Execute the page capturing the output in the stringwriter.
            HttpContext.Current.Server.Execute(_holder, sw, false);

            // Return the output.
            return sw.ToString();
        }

        #endregion

    }




Thanks
Stefan


 

5 Comments

  • You should have said im a legend in your post stef :)

  • Sorry mate forgot that one :P

  • Here is one more approach which I had to modify since in my case the controls were not derived from UserControl but from WebControl.

    public class ViewManager
    {
    public static string RenderView(string path)
    {
    return RenderView(path, null);
    }

    private static string RenderView(Page pageHolder, Control viewControl, object data)
    {
    if (data != null)
    {
    Type viewControlType = viewControl.GetType();
    FieldInfo field = viewControlType.GetField("Data");

    if (field != null)
    {
    field.SetValue(viewControl, data);
    }
    else
    {
    throw new Exception("View file: " + viewControl.ToString() + " does not have a public Data property");
    }
    }

    pageHolder.Controls.Add(viewControl);

    StringWriter output = new StringWriter();
    HttpContext.Current.Server.Execute(pageHolder, output, false);

    return output.ToString();
    }

    public static string RenderView(Type type, object data)
    {
    Page pageHolder = new Page();
    Control viewControl = pageHolder.LoadControl(type, null);
    return RenderView(pageHolder, viewControl, data);
    }

    public static string RenderView(string path, object data)
    {
    Page pageHolder = new Page();
    Control viewControl = pageHolder.LoadControl(path);
    return RenderView(pageHolder, viewControl, data);
    }
    }

    and access it as:
    Type type = typeof(CommunityServer.Controls.DisplayUserWelcome);
    return ViewManager.RenderView(type, null);

    Hope this helps someone.

    Ghanshyam

  • Here is one more approach which I had to modify since in my case the controls were not derived from UserControl but from WebControl.

    public class ViewManager
    {
    public static string RenderView(string path)
    {
    return RenderView(path, null);
    }

    private static string RenderView(Page pageHolder, Control viewControl, object data)
    {
    if (data != null)
    {
    Type viewControlType = viewControl.GetType();
    FieldInfo field = viewControlType.GetField("Data");

    if (field != null)
    {
    field.SetValue(viewControl, data);
    }
    else
    {
    throw new Exception("View file: " + viewControl.ToString() + " does not have a public Data property");
    }
    }

    pageHolder.Controls.Add(viewControl);

    StringWriter output = new StringWriter();
    HttpContext.Current.Server.Execute(pageHolder, output, false);

    return output.ToString();
    }

    public static string RenderView(Type type, object data)
    {
    Page pageHolder = new Page();
    Control viewControl = pageHolder.LoadControl(type, null);
    return RenderView(pageHolder, viewControl, data);
    }

    public static string RenderView(string path, object data)
    {
    Page pageHolder = new Page();
    Control viewControl = pageHolder.LoadControl(path);
    return RenderView(pageHolder, viewControl, data);
    }
    }

    and access it as:
    Type type = typeof(CommunityServer.Controls.DisplayUserWelcome);
    return ViewManager.RenderView(type, null);

    Hope this helps someone.

    Ghanshyam

  • Inside the UserControl I have a RadChart telerik control and that is causing the RenderView function to throw an error, has anyone face a similar challenge? Can someone please give me a hand here.

Comments have been disabled for this content.