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

发布于 2024-10-16 14:19:40 字数 2730 浏览 1 评论 0原文

我创建了一个带有名为“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; }
}

如果我随后将此代码放入 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>

我只会得到实际的文本 "< %#DataBinder.Eval(((RepeaterItem)Container.Parent).DataItem,"Url") %>"分配给 Url 属性,而不是像我预期的那样分配给计算的服务器表达式。

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

谢谢, 比约恩

I have created a UserControl with an Inner Property called "Actions", which is a List of "Action" objects. The code looks like this:

[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""> </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; }
}

If I then put this code in my aspx inside a DataRepeater, it works fine:

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

However, if I try to bind data to the attributes of the Action elements like so:

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

I merely get the actual text "<%#DataBinder.Eval(((RepeaterItem)Container.Parent).DataItem,"Url") %>" assigned to the Url property, and not the evaluated server expression as I expected.

I've googled this for hours but cannot seem to find anybody else trying to do this. Any ideas why this isn't working and how to get around it?

Thanks,
Bjoern

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风和你 2024-10-23 14:19:40

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

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

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

问候

you set the DataRepeater.Datasource in your aspx to a collection or a list static or get from database ...

instead of using DataRepeater try to make a loop inside that list you re already must create it and create new dynamic Action and that in page_load or page_init

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

Regards

鸵鸟症 2024-10-23 14:19:40

我最终使用令牌进行最里面的数据绑定,然后在绑定的控件中处理替换。所以 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();
}

I ended up using tokens for the innermost databinding and then handling the replacement in my control on bind. So the ASPX code looks like this:

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

And the added CS code like this:

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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文