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

4
我创建了一个名为 "Actions" 的内部属性的 UserControl,它是一个 "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; }
}

如果我将此代码放入我的aspx文件中的DataRepeater中,它可以正常工作:
<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>

然而,如果我尝试将数据绑定到操作元素的属性中,可以这样做:
<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>

我只是将文本"<%#DataBinder.Eval(((RepeaterItem)Container.Parent).DataItem,"Url") %>"分配给了Url属性,而不是我预期的已评估的服务器表达式。

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

谢谢, Bjoern

2个回答

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
我不太确定我理解你的意思,抱歉。我已经自己解决了,并且会在这里发布答案。 - Bjoern

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接