如何从字符串动态呈现asp.net控件?

时间:2010-02-28 13:53:39

标签: c# asp.net controls rendering

假设我有一个字符串,我从DB中检索如下:
 “Lorem ipsum dolor sit amet,consetetur sadipscing elitr,sed diam nonumy eirmod tempor invidunt ut labore et {{Hyperlink | navigateurl ='/ foo.aspx'}} dolore magna aliquyam。”

此字符串现在可以分配给标签的Text-property 我想要的是解析 {{Hyperlink | navigateurl ='/ foo.aspx'}} 并将其替换为

<asp:HyperLink ID="IDLink" runat="server" Text="foo" NavigateUrl="/foo.aspx"/>

并将包括HyperLink-Control在内的整个文本分配给标签。

这甚至可能吗?我想我可以使用反射来创建控件并设置属性。 (HyperLink-Control只是一个例子) 但是我可以设法将asp.net控件插回到字符串中以确保将超链接呈现为服务器控件吗?

我希望你明白我的意思。如果没有,请随时发表评论。

编辑1:

  

你是什么意思“分配整体   文本,包括HyperLink-Control   标签。“?你能解释一下,   这样做的原因是什么?

我认为将控件分配给字符串是行不通的,因为asp.net控件不能适应字符串。

经过一番思考,我找到了实现目标的方法。那就是创建一个占位符(我将其命名为A)。其中将添加一些Literal控件。另外我会创建一个占位符(我将其命名为B),将我的超链接添加到B中,并将A添加到B中。 但我认为是过度杀戮的方式。

我开始考虑这个问题的原因是为了获得对Server.MapPath的访问而不替换字符串中的出现。我希望能够在CMS中使用相对路径,从远程超链接获取类似NavigateUrl属性的路径。 不过我认为我对动态创建的问题值得考虑

2 个答案:

答案 0 :(得分:4)

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();
        }
    }

答案 1 :(得分:1)

如果您将文本分成2个标签而不是1个,我相信这是可能的。我写了一个快速示例来演示。从数据库解析字符串时,如果动态控件之前和之后有文本,则只需设置DynamicControl的BeginText和EndText属性。

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)
    {

    }    
}