I'm not sure if the title I've picked is the best way to describe this but it'll do. I've been using a LoginView within the ItemTemplate of a FormView to determine what the "available actions" are for a page. Here's an example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<asp:FormView ID="fvApplication" runat="server"> | |
<ItemTemplate> | |
<h1>Application Form</h1> | |
<!-- Lots of detail about application in here --> | |
<asp:LoginView ID="lvOptions" runat="server"> | |
<RoleGroups> | |
<asp:RoleGroup Roles="Provider"> | |
<ContentTemplate> | |
<asp:LinkButton runat="server" OnClick="Offer_Click" | |
Visible='<%# ApplicationStatus.Sent == (ApplicationStatus) Eval("Status") %>'>Make Offer</asp:LinkButton> | |
<asp:LinkButton runat="server" OnClick="Reject_Click" | |
Visible='<%# ApplicationStatus.Sent == (ApplicationStatus) Eval("Status") %>'>Reject Application</asp:LinkButton> | |
</ContentTemplate> | |
</asp:RoleGroup> | |
<asp:RoleGroup Roles="Student"> | |
<ContentTemplate> | |
<asp:LinkButton runat="server" OnClick="Send_Click" | |
Visible='<%# ApplicationStatus.Unsent == (ApplicationStatus) Eval("Status") %>'>Send</asp:LinkButton> | |
<asp:LinkButton runat="server" OnClick="Accept_Click" | |
Visible='<%# ApplicationStatus.Offered == (ApplicationStatus) Eval("Status") %>'>Accept Offer</asp:LinkButton> | |
<asp:LinkButton runat="server" OnClick="Refuse_Click" | |
Visible='<%# ApplicationStatus.Offered == (ApplicationStatus) Eval("Status") %>'>Refuse Offer</asp:LinkButton> | |
</ContentTemplate> | |
</asp:RoleGroup> | |
</RoleGroups> | |
</asp:LoginView> | |
</ItemTemplate> | |
</asp:FormView> |
This works fine when first coming into the page. The LoginView picks out the right template depending on the user's role, and when my Application object is databound to the FormView, the visibility of the individual buttons is set correctly. (Note that this is my own custom Application object, nothing to do with the framework.)
However, all is not well when making some changes to the application elsewhere on the page and then rebinding the FormView (i.e. this time we're dealing with a postback). This time, the LoginView fires its ViewChanging and ViewChanged events. I guess technically it's correct, as what I'm looking at on the page (i.e. my "view") may have changed if the various button visibilities have changed. However, my role hasn't changed, and hence the template the LoginView is using hasn't changed, which is kind of what I was expecting the ViewChanged event to mean.
Anyway, the problem comes in that somewhere in the middle of this "ooh, my view's changed" moment that the LoginView has, it blats its control hierarchy and recreates it, only this happens after the FormView was databound, and thus all the button visibilities are lost, resulting in them all going back to their default setting.
My workaround for now is to perform a Response.Redirect() and let everything create itself from scratch again as the way my page is setup allows this without any problems. However, if you need to remain within the context of a postback, I suggest using something like a MultiView instead of a LoginView, and manually set the correct view in there yourself at an appropriate time.
Suggestions for better solutions are, as always, welcome.