如何将 If...Then 逻辑复制为 Web 控件?

发布于 2024-09-14 19:21:12 字数 811 浏览 12 评论 0原文

我有一位设计师在 ASPX 级别工作。他不做 C#、不做代码隐藏、不编译等等。他是一个纯粹的设计师,从事 HTML 和服务器控件工作。

我需要一个条件控制——一个 If...Then 类型的东西。通常,我会这样做:

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

有没有办法在没有数据绑定语法的情况下执行类似的操作?例如:

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

是否有某种方法可以扩展占位符以允许此操作?我摆弄了一下,但最后,我有一个条件,我基本上必须编译。

现在,数据绑定语法没有任何问题,但还有一点……奇怪,设计人员必须理解。此外,它没有给我“其他”语句。像这样的东西就太好了...

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

I have a designer working at the ASPX level. He doesn't do C#, doesn't do code-behinds, doesn't compile, etc. He's a pure designer, working with HTML and server controls.

I need a conditional control -- an If...Then-ish type thing. Normally, I would do this:

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

Is there any way to do something like this without the databinding syntax? Something like:

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

Is there some kind of way to extend a placeholder to allow this? I've fiddled around a bit, but in the end, I have a conditional that I essentially have to compile.

Now, there's nothing wrong with the databinding syntax, but's just one more bit of...weirdness, the a designer is going to have to understand. Additionally, it doesn't give me "else" statements. Something like this would be great...

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

可爱暴击 2024-09-21 19:21:12

与其编写控件,

asp:If

为什么不使用:

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

Instead of writing control

asp:If

why not use:

<% if expression
       { %>
    Yellow
    <% } %>
    <% else
        {%>
    Red
    <% } %>
卷耳 2024-09-21 19:21:12

考虑到代码隐藏文件已经消失,因为设计者可能没有得到 VS,我认为代码更少的更简单的解决方案可能更优先:

<%@ 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>

可以更改为另一种类型Web控件,如等。我认为几乎所有的点网控件都具有visible属性,因此您可以随时隐藏/显示它们。

Taking into account that codebehind files are out as the designer probably not got VS, I think a simpler solution with less code may be more preferential:

<%@ 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>

the <asp:panel> could be changed to another type of web control, like <asp:label> etc. I think almost all dot net controls have the visible property, so you can hide/show them at any time.

惟欲睡 2024-09-21 19:21:12

数据绑定语法有两个问题:首先,与使用纯文本相比,它对设计人员来说有点奇怪,其次,它要求设计人员记住反转“else”块中的“if”测试。

第一个问题可能会让你的设计师有点恼火,但第二个问题要严重得多,因为它迫使你的设计师像程序员一样思考(反转布尔逻辑!)并使每个 if/else 块都成为你需要测试的可能错误在您的设计师交出模板后。

我的建议:使用数据绑定语法,但通过创建仅需要在 If 控件上而不是在 Else 控件上需要数据绑定测试代码的自定义控件来解决更严重的问题。当然,您的设计人员将不得不输入更多字符,但其他更严重的问题将不会出现,并且您的性能也不会像每次页面运行时都必须动态编译代码那样受到影响。

这是我编写的一个示例来说明:

<%@ 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>

这是底层控件,它们只是 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");
            }
        }
    }
}

如果您希望它更简洁,您可以轻松缩短标记名称(通过更改类名称)和/或标签前缀)。您还可以创建一个新属性(例如“test”)来代替“Visible”。

如果您确实想要摆脱 <%# %>,您可以使用许多不同的技巧来利用 CodeDOM 或其他方式来动态编译代码,尽管性能将是一个挑战,因为您可能最终会在每次页面运行时动态编译代码,但它可能会引入讨厌的安全问题等等。我会远离那个。

The data-binding syntax has two problems: first it's a little weirder for your designer vs. using plain text, and second it requires the designer to remember to invert the "if" test in your "else" block.

The first problem may annoy your designer a little, but the second problem is much more severe, because it forces your designer to think like a programmer (inverting boolean logic!) and makes every if/else block into a possible bug you need to test for after your designer hands over a template.

My suggestion: use data-binding syntax, but fix the more severe problem by creating custom controls that only require data-binding test code on the If control, but not on the Else control. Sure your designers will have to type a few more characters, but the other more severe problems won't apply and your performance won't suffer as it would if you had to dynamically compile code each time your page ran.

Here's an example I coded up to illustrate:

<%@ 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>

Here's the underlying controls, which are simply wrappers around 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");
            }
        }
    }
}

If you want it more concise, you can easily shorten the tag name (by changing the class names and/or tag prefix). You can also create a new property (e.g. "test") to use instead of "Visible".

If you really want to get rid of the <%# %>, there are likley many different tricks you can use to leverage CodeDOM or other ways to dynamically compile code, although performance will be a challenge since you'll probably end up dynamically compiling code each time the page runs, it may introduce pesky security issues, and more. I'd stay away from that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文