2010-08-18 14 views
2

J'ai un designer qui travaille au niveau ASPX. Il ne fait pas de C#, ne fait pas de code-behind, ne compile pas, etc. Il est un concepteur pur, travaillant avec des contrôles HTML et serveur.Comment puis-je répliquer Si ... Alors logique comme un contrôle Web?

J'ai besoin d'un contrôle conditionnel - une chose de type If ... Then-ish. Normalement, je fais ceci:

<asp:Placeholder Visible='<%# DateTime.Now.Day == 1 %>' runat="server"> 
    It's the first day of the month! 
</asp:PlaceHolder> 

Est-il possible de faire quelque chose comme ça, sans la syntaxe de liaison de données? Quelque chose comme:

<asp:If test="DateTime.Now.Day == 1" runat="server"> 
    It's the first day of the month! 
</asp:If> 

Existe-t-il une sorte de façon d'étendre un espace réservé pour permettre cela? J'ai un peu bidouillé, mais à la fin, j'ai un conditionnel que je dois essentiellement compiler.

Maintenant, il n'y a rien de mal à la syntaxe de la liaison de données, mais c'est juste un peu plus de ... étrangeté, le concepteur va devoir comprendre. De plus, cela ne me donne pas d'autres instructions. Quelque chose comme ça serait génial ...

<asp:If test="DateTime.Now.Day == 1" runat="server"> 
    It's the first day of the month! 
    <asp:Else> 
    It's not the first day of the month! 
    </asp:Else> 
</asp:If> 
+0

Si j'avais ce problème, je mettrais deux contrôles de panneau, un pour chaque condition, définissez moi-même leurs attributs visibles respectifs, et disons simplement à mon programmeur de les coder correctement. Cela m'amènerait naturellement à insérer une infrastructure de test en même temps. –

Répondre

0

La syntaxe de liaison de données a deux problèmes: d'abord, il est un peu plus étrange pour votre concepteur par rapport à l'aide du texte brut, et la seconde, il exige le concepteur de se rappeler d'inverser la "if" tester dans votre bloc "else". Le premier problème peut gêner un peu votre concepteur, mais le second problème est beaucoup plus grave, car il force votre concepteur à penser comme un programmeur (inversant la logique booléenne!) Et fait de chaque bloc if/else un bug possible vous devez tester pour après que votre concepteur remette un modèle. Ma suggestion: utilisez la syntaxe de liaison de données, mais résolvez le problème le plus grave en créant des contrôles personnalisés qui ne nécessitent qu'un code de test de liaison de données sur le contrôle If, ​​mais pas sur le contrôle Else. Bien sûr, vos concepteurs devront taper quelques caractères de plus, mais les autres problèmes les plus graves ne s'appliqueront pas et vos performances ne souffriront pas si vous deviez compiler dynamiquement du code chaque fois que votre page fonctionnait.

Voici un exemple que j'ai codé pour illustrer:

<%@ Page Language="C#"%> 
<%@ Register Assembly="ElseTest" TagPrefix="ElseTest" Namespace="ElseTest"%> 

<script runat="server"> 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     DataBind(); 
    } 
</script> 

<html> 
<body> 

    <ElseTest:IfControl runat="server" visible="<%#1 == 1 %>"> 
     This should be visible (in "if" area) 
    </ElseTest:IfControl> 
    <ElseTest:ElseControl runat="server"> 
     This should not be visible (in "else" area) 
    </ElseTest:ElseControl> 

    <br /><br /> 

    <ElseTest:IfControl runat="server" visible="<%#0 == 1 %>"> 
     This should not be visible (in "if" area) 
    </ElseTest:IfControl> 
    <ElseTest:ElseControl runat="server"> 
     This should be visible (in "else" area) 
    </ElseTest:ElseControl> 

</body> 
</html> 

est ici les contrôles sous-jacents, qui sont simplement des emballages autour asp:Literal:

using System; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

[assembly: TagPrefix("ElseTest", "ElseTest")] 
namespace ElseTest 
{ 
    // simply renames a literal to allow blocks of data-bound-visibility 
    [ToolboxData("<{0}:IfControl runat=\"server\"></{0}:IfControl>")] 
    public class IfControl : Literal 
    { 
    } 

    [ToolboxData("<{0}:ElseControl runat=\"server\"></{0}:ElseControl>")] 
    public class ElseControl : Literal 
    { 
     public override bool Visible 
     { 
      get 
      { 
       // find previous control (which must be an IfControl). 
       // If it's visible, we're not (and vice versa) 
       for (int i = Parent.Controls.IndexOf(this)-1; i >= 0; i--) 
       { 
        Control c = Parent.Controls[i]; 
        if (c is IfControl) 
         return !c.Visible; // found it! render children if the if control is not visible 
        else if (c is Literal) 
        { 
         // literals with only whitespace are OK. everything else is an error between if and then 
         Literal l = c as Literal; 
         string s = l.Text.Trim(); 
         if (s.Length > 0) 
          throw new ArgumentException("ElseControl must be immediately after an IfControl"); 
        } 
       } 
       throw new ArgumentException("ElseControl must be immediately after an IfControl"); 
      } 
      set 
      { 
       throw new ArgumentException("Visible property of an ElseControl is read-only"); 
      } 
     } 
    } 
} 

Si vous voulez plus concise, vous pouvez facilement raccourcir le nom du tag (en changeant les noms de classe et/ou le préfixe de tag). Vous pouvez également créer une nouvelle propriété (par exemple "test") à utiliser à la place de "Visible".

Si vous vraiment voulez vous débarrasser de la <%# %>, il y a beaucoup de trucs likley différentes que vous pouvez utiliser pour tirer parti de CodeDOM ou d'autres façons de compiler dynamiquement le code, bien que la performance sera un défi puisque vous finirez probablement compilation dynamique du code chaque fois que la page s'exécute, il peut introduire des problèmes de sécurité embêtants, et plus encore. Je resterais loin de ça.

+0

Pas tout à fait ce que je cherchais, mais c'est bien pensé et un pas dans la bonne direction. – Deane

2

lieu de contrôle d'écriture

asp:If 

pourquoi ne pas utiliser:

<% if expression 
     { %> 
    Yellow 
    <% } %> 
    <% else 
     {%> 
    Red 
    <% } %> 
+0

Notez que cela ne fonctionnera pas si l'expression dépend des données d'exécution générées dans Page_Load, dans le code de publication, etc. car l'expression ci-dessus est évaluée très tôt dans le cycle de vie de la page avant l'exécution des gestionnaires d'événements côté serveur. –

2

En tenant compte du fait que CodeBehind fichiers sont comme le concepteur probablement pas obtenu VS, je pense qu'une solution plus simple avec moins de code peut-être plus préférentielle:

<%@ Page Language="C#"%> 

<script runat="server"> 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     if (DateTime.Now.Day == 1) 
     { 
      DateTestPanelFirst.visible = true; 
      DateTestPanelOther.visible = false; 
     } 
    } 
</script> 

<html> 
<body> 

<asp:panel runat="server" id="DateTestPanelFirst" visible="false"> 
    It's the first day of the month! 
<asp:panel> 

<asp:panel runat="server" id="DateTestPanelOther"> 
    It's not the first day of the month! 
<asp:panel> 

</body> 
</html> 

le <asp:panel> pourrait être changé pour Ano le type de contrôle Web, comme <asp:label> etc Je pense que presque tous les contrôles dot net ont la propriété visible, de sorte que vous pouvez les cacher/montrer à tout moment.