How to dynamically render asp.net controls from string?
Let's say I have a string that I retrieve from a DB like:
"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et {{Hyperlink|navigateurl='/foo.aspx'}} dolore magna aliquyam."This string may now get assigned to the Text-property of a label.
What I want is to parse {{Hyperlink|navigateurl='/foo.aspx'}} and replace it with<asp:HyperLink ID="IDLink" runat="server" Text="foo" NavigateUrl="/foo.aspx"/>
and assign the whole text including the HyperLink-Control to the Label.
Is that even possible? I think I could use reflection to create the control and set the properties. (the HyperLink-Control was just an example) But can I manage to insert the asp.net control back into the string to ensure the hyperlinks rendering as server contorl?
I hope you understand what I want. If not, feel free to post comments.
Edit1:
what do you mean by "assign the whole text including the HyperLink-Control to the Label."? can you explain a bit, the reason for doing so ?
I think it won't work to assign the control into the string, because a asp.net control cannot be fit into a string.
After some 开发者_如何学Cthinking I found a way to achieve my goal. That would be to create a placeholder (I name it A). Therein some Literal control will be added. In addition I would create a placeholder (I name it B), add my Hyperlink into B, and add A into B. But I think is way to overkill.
The reason why I started thinking about this, was to gain access to Server.MapPath without replacing occurences in the string. I want to be able to use relative paths in my CMS, that get rendered like the NavigateUrl property from a hyperlink. Nevertheless I think my question with the dynamically creation is worth thinking about
public class Program
{
static void Main(string[] args)
{
ParserBase parser = new ParserBase();
Console.WriteLine(parser.DynamicRenderControl<HyperLink>(parser.Parse("")));
Console.ReadLine();
}
}
public class ParserBase
{
public virtual Dictionary<string, string> Parse(string stringToParse)
{
//...
// parse the stringToParse
//...
Dictionary<string, string> parsedPropertiesValues = new Dictionary<string, string>();
parsedPropertiesValues.Add("NavigateUrl", @"http://www.koolzers.net");
return parsedPropertiesValues;
}
protected virtual void SetProperty<T>(T obj, string propertyName, string value) where T : WebControl
{
typeof(T).GetProperty(propertyName).SetValue(obj, value, null);
}
public string DynamicRenderControl<T>(Dictionary<string, string> parsedPropertiesValues) where T : WebControl, new()
{
StringBuilder sb = new StringBuilder();
using (T control = new T())
{
foreach (KeyValuePair<string, string> keyValue in parsedPropertiesValues)
{
SetProperty<T>(control, keyValue.Key, keyValue.Value);
}
using (StringWriter tw = new StringWriter(sb))
{
using (HtmlTextWriter w = new HtmlTextWriter(tw))
{
control.RenderControl(w);
}
}
}
return sb.ToString();
}
}
I believe this is possible if you split your text into 2 labels instead of one. I wrote up a quick sample to demonstrate. When you parse your string from the db, if there is text before and after your dynamic control than just set the BeginText and EndText properties of DynamicControl.
public class DynamicControl
{
public String BeginText { get; set; }
public String EndText { get; set; }
public String ControlName { get; set; }
public Dictionary<String, String> ControlProperties { get; set; }
}
public partial class _Default : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//read strings from db
var dynamicControlStrings = GetStringsFromDB();
//parse strings into list of dynamicControls
var dynamicControls = ParseStringsToDynamicControls(dynamicControlStrings);
foreach (var dynamicControl in dynamicControls)
{
CreateControl(dynamicControl.BeginText, dynamicControl.EndText, dynamicControl.ControlName, dynamicControl.ControlProperties);
}
}
private void CreateControl(string beginText, string endText, string controlName, Dictionary<String, String> controlProperties)
{
var beginLabel = new Label()
{
Text = beginText
};
var dynamicControl = GenerateDynamicControl(controlName, controlProperties);
var endLabel = new Label()
{
Text = endText
};
var span = new HtmlGenericControl("span");
span.Controls.Add(beginLabel);
span.Controls.Add(dynamicControl);
span.Controls.Add(endLabel);
form1.Controls.Add(span);
}
//you would create your dynamic control here (such as the hyperlink) based on the control name and use reflection to set the properties
private WebControl GenerateDynamicControl(string controlName, Dictionary<String, String> controlProperties)
{
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
精彩评论