【问题标题】:How to dynamically render asp.net controls from string?如何从字符串动态呈现 asp.net 控件?
【发布时间】:2023-04-07 06:20:01
【问题描述】:

假设我有一个从数据库中检索到的字符串,例如:
“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 只是一个例子) 但是我可以设法将 asp.net 控件插入回字符串中以确保超链接呈现为服务器控件吗?

我希望你明白我想要什么。如果没有,请随时发布 cmets。

编辑1:

“分配整体”是什么意思 包含超链接控件的文本 给标签。”?你能解释一下吗? 这样做的原因是什么?

我认为将控件分配到字符串中是行不通的,因为 asp.net 控件无法放入字符串中。

经过一番思考,我找到了实现目标的方法。那将是创建一个占位符(我将其命名为 A)。其中将添加一些文字控件。此外,我将创建一个占位符(我将其命名为 B),将我的超链接添加到 B,然后将 A 添加到 B。 但我认为这是矫枉过正的方式。

我开始考虑这个的原因是为了在不替换字符串中出现的情况下访问 Server.MapPath。我希望能够在我的 CMS 中使用相对路径,这些路径像超链接中的 NavigateUrl 属性一样呈现。 尽管如此,我认为我关于动态创建的问题值得思考

【问题讨论】:

  • "assign the whole text including the HyperLink-Control to the Label." 是什么意思?你能解释一下,这样做的原因吗?

标签: c# asp.net controls rendering


【解决方案1】:
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();
        }
    }

【讨论】:

  • 不错的一个。还没有渲染子控件并将 html 输出添加回字符串。
  • 这就是我要找的东西!:)
【解决方案2】:

我相信如果您将文本分成 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)
    {

    }    
}

【讨论】:

  • 是的,我想到了这样的想法。您认为这会有多高效?
  • 反射肯定比直接访问某些对象要慢,但我认为这篇博文总结了很多常见的误解west-wind.com/weblog/posts/351.aspx。我假设您不会在每页自动生成数十万个控件,所以您应该没问题。不过,您可能想考虑一下您的动态控制令牌。如果您打算使用 Activator.CreateInstance(...) 之类的东西,您将希望在您的令牌中包含完整的类型名称,以使您自己更轻松。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 2013-03-11
相关资源
最近更新 更多