Länka namn till personsida

Jag fortsätter mina förändringar av den ItemTemplate som jag bloggat om tidigare. Efter senaste bloggposten ser min ItemTemplate nu ut så här;

   <ItemTemplate>
       <div class="item">
           <div class="icon"><img src="../images/icon_board.png" /></div>
           <span class="credit">
               <asp:Label ID="authorNameLabel" runat="server" Text='<%# Bind("authorName") %>' />
               <br />
               <asp:Label ID="dateLabel" runat="server" Text='<%# Bind("timeStamp", "{0:d}") %>' />
               <asp:Label ID="timeLabel" runat="server" Text='<%# Bind("timeStamp", "{0:t}") %>' />
           </span>
           <br />
           <asp:Label ID="messageLabel" runat="server" Text='<%# Bind("message") %>' />
           <asp:LoginView ID="LoginView1" runat="server">
               <RoleGroups>
                   <asp:RoleGroup Roles="Admin">
                       <ContentTemplate>
                           <br />
                           <asp:Button ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="Ta bort" />
                       </ContentTemplate>
                   </asp:RoleGroup>
               </RoleGroups>                                
           </asp:LoginView>
       </div>
   </ItemTemplate>

I denna bloggpost ska vi fokusera på att få namnet på användaren länkat till en sida som presenterar just den personen. Något som visade sig vara betydligt enklare än min första lösning på problemet. Återkommer till det. Målet är alltså att skapa en länk i stil med person.aspx?userId=2938219038. Den SqlDataSource som ListView-kontrollen är kopplad till hämtar förstås upp användarens UserId så att jag har tillgång även till det via ett Bind-kommando, <%# Bind("UserId") %>. Då kan man ju tycka att det borde funka att ändra labelkontrollen authorNameLabel till en HyperLink så här;

<asp:HyperLink ID="lnkAuthorName" runat="server" Text='<%# Eval("authorName") %>' NavigateUrl='~/Authenticated/person.aspx?userID=<%# Bind("userId") %>' />

Men se det går inte. Sidan går utmärkt att köra men resultatet blir en länk med följande slut: person.aspx?userID=%3C%#%20Bind(%22userId%22)%20%%3E. Mitt Bind-kommando utvärderas alltså inte av servern och den lösning jag då kom på var att göra om till en LinkButton på följande sätt;

<asp:LinkButton ID="NameLink" runat="server" Text='<%# Eval("authorName") %>' CommandArgument='<%# Bind("userId") %>' OnClick="nameLink_Click" />

På så vis gör jag inga konstigheter med Bind-kommandot. Som tillägg till detta måste jag dock implementera en metod på server-sidan som tar hand om klicket - nameLink_Click. Den metoden valde jag att placera i den page-klass jag skapat som alla min sidor ärver från, på så sätt kan jag använda denna metod från alla sidor i alla sammanhang där ett namn ska länkas till en personsida.

public class ttPage : System.Web.UI.Page
{
    /.../

    public void nameLink_Click(object sender, EventArgs e)
    {
        string userID = ((IButtonControl)sender).CommandArgument;
        Response.Redirect(this.ResolveUrl("~/Authenticated/person.aspx?userId=" + userID));
    }

    /.../
}

Vad händer här då? Jo, UserId vill jag ta från knappens CommandArgument och eftersom sender är en referens till det objekt som triggat eventet typar jag den till en IButtonControl. Vad är nu detta då? Jo IButtonControl är ett interface som implementeras av alla knappkontroller, som LinkButton och Button, och det är i IButtonControl som CommandArgument definieras. Självklart hade jag kunnat typa till en LinkButton men då låser jag fast mig vid att mina namnlänkar aldrig kommer vara av någon annan knapptyp, så det här blir helt enkelt en snyggare lösning. På nästa rad skickar jag webbläsaren vidare till rätt sida med Response.Redirect genom att konkatenera ihop url:en med userId:t. Page.ResolveUrl utvärderar ~-tecknet så att man hamnar där man ska. (~-tecknet symboliserar roten i web-applikationen) Det här är dock ingen snygg lösning egentligen.

Ikväll när jag googlar för att kolla upp skillnaden mellan Eval och Bind hamnar jag i denna forumtråd och ett inlägg där leder mig till att googla på "container.dataitem vs eval" +asp.net vilket i sin tur leder mig till denna artikel där en kommentar uppmärksammar mig på att jag kan lösa mitt problem på exakt samma sätt som med datumutskriften i tidigare blogginlägg. Nämligen så här;

<asp:HyperLink ID="lnkAuthorName" runat="server" Text='<%# Eval("authorName") %>' NavigateUrl='<%# Bind("userId", "~/Authenticated/person.aspx?userID={0}") %>' />

Fördelen med detta är förstås att jag blir av med PostBacken som en LinkButton orsakar, och jag blir av med den Response.Redirect som jag hade i nameLink_Click-metoden... Sammanfattningsvis kan man säga att det lönar sig att vänta ett par dagar innan man skriver bloggposten. ;-)

No comments :

Post a Comment