Ayende @ Rahien

Unnatural acts on source code

rails:ConditionalRender - still trying to get WebForms to work right

Well, as it turns out, there are some things that you can do to make WebForms more palatable. Smart use of ITemplate and some additional magic can take you a fairly long way. I am still severely limited (splitting behavior between markup & code behind is extremely annoying) in what I can do, but it  is good to know that it is possible:

<rails:ConditionalRenderer runat="server" 
    Condition="<%# ((Policy)Container.DataItem).Expired %>"
    DataItem="<%# Container.DataItem %>" >
    <WhenTrue>
        Policy has expired!
    </WhenTrue>    
    <WhenFalse>
        Policy is valid until <%# Eval("ExpiryDate") %>
    </WhenFalse>
</rails:ConditionalRenderer>
 
I am using it inside a repeater to keep the presentation logic in a single place.
 
The code to make this happen is something like this (typed from memory, you need about 80 lines to get it right).
 
[ParseChildren(true)]
public class ConditionalRenderer : Control, INamingContainer
{
    public bool Condition { get { .. } set { .. } }

    [Templatecontainer(ConditionalRenderer)]
    public ITemplate WhenTrue { get { .. } set { .. } } 
    [Templatecontainer(ConditionalRenderer)]
    public ITemplate WhenFalse { get { .. } set { .. } }

    public object DataItem { get { .. } set { .. } }
    
    public override void EnsureChildControls()
    {
        if (Condition)
            WhenTrue.InstansiateIn(this);
        else
            WhenFalse.InstansiateIn(this);
    }
}

Comments

Aaron Jensen
06/06/2007 09:24 PM by
Aaron Jensen

I'm sure you know this.. but MultiView will do just this out of the box (albeit a bit uglier and less expressive) I think... it's been a while since I've used it, but try something like this:

<asp:MultiView runat="server" ActiveViewIndex="<%# Condition ? 0 : 1%>">

<asp:View runat="server">

True case

</asp:View>

<asp:View runat="server">

False case

</asp:View>

</asp:MultiView>

We also used asp:Views w/ visible="<%# Condition %>" for things that didn't need an else.

Ayende Rahien
06/06/2007 09:30 PM by
Ayende Rahien

@Aaron,

Interesting, this is the first I see this approach.

Now I won't have to implement the SwitchRenderer :-)

joe
06/06/2007 11:08 PM by
joe

A lot of people forget that you can still write old school asp style in ASP.NET. What I choose most of the time over using controls is something more like this:

<% foreach (Policy policy in Policies) { %>

<% if (policy.Expired ) { %>

  Policy expired

<% } else { %>

  Policy valid until <%= policy.ExpiryDate %>

<% } %>

<% } %>

oh, and if you insist on using databinding can't you just write this:

<%# ((Policy)Container.DataItem).Expired ? "Policy expired" : "Policy valid until " + ((Policy)Container.DataItem).ExpiryDate.ToString() %>

Ayende Rahien
06/06/2007 11:24 PM by
Ayende Rahien

joe,

put ~ 50 lines of complex HTML on each branch, and you will get a mess.

Jeff Perrin
06/07/2007 02:49 AM by
Jeff Perrin

Ayende,

Put the complex html for each branch in a usercontrol.

Ayende Rahien
06/07/2007 04:41 AM by
Ayende Rahien

@Jeff,

Yes, but then I need to manage the state transfer in the code behind.

It also means that I need to create user controls for non reusable stuff.

Comments have been closed on this topic.