ASP.Net绑定自定义控件的内部属性的属性

时间:2011-02-09 12:19:39

标签: c# asp.net data-binding user-controls nested

我创建了一个UserControl,其内部属性称为“Actions”,它是一个“Action”对象列表。代码如下所示:

[ParseChildren(true)]
public class MyLink : UserControl
{
    readonly List<Action> _actions = new List<Action>();

    [PersistenceMode(PersistenceMode.InnerProperty)]
    public List<Action> Actions
    {
        get { return _actions; }
    }

    public string Text { get;set; }
    public string Url { get;set; }
    public string MenuName { get; set; }

    protected override void Render(HtmlTextWriter writer)
    {
        //Build link
        StringBuilder sb = new StringBuilder();
        sb.Append(@"
            <table class=""myLink"">
                <tr>
                    <td class=""myLinkLeft""><a href=" + Url + @">" + Text + @"</a></td>
                    <td class=""myLinkRight " + MenuName + @"_trigger"">&nbsp;</td>
                </tr>
            </table>
        ");

        //Build actions
        sb.Append("<ul id=\"" + MenuName + "_actions\" class=\"contextMenu\">");

        foreach (Action action in _actions)
        {
            sb.Append("<li class=\"" + action.CssClass + "\"><a href=\"#" + action.Url + "\">" + action.Text + "</a></li>");
        }

        sb.Append("</ul>");

        writer.Write(sb.ToString());
    }
}

public class Action : UserControl
{
    public string Url { get; set; }
    public string Text { get; set; }
    public string ImageUrl { get; set; }
    public string CssClass { get; set; }
}

如果我将此代码放在DataRepeater中的aspx中,它可以正常工作:

<uc1:MyLink runat="server" Url="/" Text='<%#DataBinder.Eval(Container.DataItem,"Text") %>' MenuName="contextMenu" id="contextMenu">
    <Actions>
        <uc1:Action runat="server" Url="http://mysite.com" Text="MyUrl"  />
        <uc1:Action runat="server" Url="http://google.com" Text="Google" />
    </Actions>
</uc1:MyLink>

但是,如果我尝试将数据绑定到Action元素的属性,如下所示:

<uc1:MyLink runat="server" Url="/" Text='<%#DataBinder.Eval(Container.DataItem,"Text") %>' MenuName="contextMenu" id="contextMenu">
    <Actions>
        <uc1:Action runat="server" Url='<%#DataBinder.Eval(((RepeaterItem)Container.Parent).DataItem,"Url") %>' Text="MyUrl"  />
        <uc1:Action runat="server" Url="http://google.com" Text="Google" />
    </Actions>
</uc1:MyLink>

我只是得到实际文本“&lt;%#DataBinder.Eval(((RepeaterItem)Container.Parent).DataItem,”Url“)%&gt;”分配给Url属性,而不是我期望的评估服务器表达式。

我用谷歌搜索了几个小时,但似乎找不到其他任何人试图这样做。任何想法为什么这不起作用以及如何解决它?

谢谢, 比约恩

2 个答案:

答案 0 :(得分:0)

将aspx中的DataRepeater.Datasource设置为集合或静态列表或从数据库中获取...

而不是使用DataRepeater尝试在该列表中创建一个循环,您必须创建它并创建新的动态Action,并在page_load或page_init

Action a;
foreach(object x in objects)
{
   a= new Action();
   a.Url = ... ;
   a.Text = ... ;
   MyLink.Actions.Add(a);
}

此致

答案 1 :(得分:0)

我最终使用令牌进行最内部数据绑定,然后在绑定控件中处理替换。所以ASPX代码如下所示:

<uc1:MyLink runat="server" Url="/">
   <Actions>
      <uc1:Action Url="/Page.aspx?cpr=##cpr##&opgaveId=##id##" />
      <uc1:Action Url="/Test.aspx" />
   </Actions>
</uc1:MyLink>

添加的CS代码如下:

protected override void OnInit(EventArgs e)
{
    DataBinding += BindData;
}

public void BindData(object sender, EventArgs e)
{
    MyLink pl = (MyLink) sender;
    IDataItemContainer container = (IDataItemContainer) pl.NamingContainer;
    foreach (Action action in _actions)
    {
        action.Url = ReplaceTokens(action.Url, container);
        action.Text = ReplaceTokens(action.Text, container);
    }
}

private static string ReplaceTokens(string text, IDataItemContainer container)
{
    Regex re = new Regex("##.*?##", RegexOptions.Compiled | RegexOptions.Singleline);
    StringBuilder sb = new StringBuilder(text);

    foreach (Match m in re.Matches(text))
    {
        string tokenValue = DataBinder.GetPropertyValue(container.DataItem, m.Value.Substring(2, m.Value.Length - 4), "{0}");
        sb.Replace(m.Value, tokenValue);
    }
    return sb.ToString();
}