ASP.Net связывание атрибутов внутреннего свойства пользовательского элемента управления - PullRequest
3 голосов
/ 09 февраля 2011

Я создал UserControl с внутренним свойством под названием «Действия», которое представляет собой список объектов «Действие». Код выглядит так:

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

Однако, если я попытаюсь привязать данные к атрибутам элементов 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, а не оцененное выражение сервера, как я ожидал .

Я гуглил это часами, но, похоже, не могу найти никого, кто пытался бы это сделать. Есть идеи, почему это не работает и как обойти это?

Спасибо, Бьорн

Ответы [ 2 ]

0 голосов
/ 15 апреля 2011

В итоге я использовал токены для самой внутренней привязки данных, а затем обработал замену в своем контроле на привязке. Поэтому код 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();
}
0 голосов
/ 12 апреля 2011

вы устанавливаете DataRepeater.Datasource в вашем aspx как коллекцию или список статический или получать из базы данных ...

вместо использования DataRepeater попытайтесь создать цикл внутри этого списка, который вы уже должны создатьи создайте новое динамическое действие и это в page_load или page_init

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

Regards

...