题
我正在开发一个需要能够支持两种或多种外观并在运行时可更改的网站。我希望能够通过 CSS 开关来处理更改,但看起来我需要为每个设计使用不同的母版页。
那么,在运行时设置母版页的最佳方法是什么?Page.MasterPageFile 只能在Page.OnPreInit 事件中设置。看起来解决方案是让我的所有页面继承处理 PreInit 事件的公共基础,或者使用执行此操作的 HttpModule。
有什么建议吗?
解决方案
我之前已经这样做过一次,我完全按照您所描述的方式进行了操作(使所有页面都从具有 OnPreInit 事件的自定义页面继承)。另外,我在 Global.asax.cs 中有一个自定义的 Application_PreRequestHandlerExecute 用于设置 Page.StyleSheetTheme 来进行不需要不同母版页的图像/css 更改。
其他提示
与其使用两个不同的母版页,不如使用一个母版页来动态加载不同的用户控件和内容 HTML 文本?
我感受到你的痛苦。我搜索了大约一个小时(如果不是更多的话)来解决这个问题,但没有成功。当您有数百个页面时,“只需在每个页面上从 PreInit 调用它”并不是一个简单的答案。但后来我意识到,我花在寻找解决方案上的时间比在每个页面上都花的时间要多。
但是,我想根据 Profile 属性设置 MasterPageFile,这样每页大约需要 5 行代码,这是可维护性的噩梦。不管怎样,“不要重复自己”,对吧?
因此,我在 App_Code 文件夹的模块中创建了一个扩展方法,以使其更容易且更易于维护。
Public Module WebFunctions
<System.Runtime.CompilerServices.Extension()> _
Public Sub SetMaster(ByVal page As Page)
Dim pb As ProfileCommon = DirectCast(HttpContext.Current.Profile, ProfileCommon)
If pb IsNot Nothing Then
page.MasterPageFile = pb.MasterPage
End If
End Sub
End Module
然后在每个页面的 PreInit 上,我只是这样调用:
Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit
Me.SetMaster()
End Sub
处理 PreInit 并插入加载正确母版页所需的一行代码非常容易。
this.Page.MasterPageFile = "~/default.master";
如果没有令人信服的理由不走这条路,我就会这么做,无论您在哪里处理 PreInit。
我很好奇是什么决定了页面的外观?是用户点击按钮来更改主题吗?是否基于用于访问该网站的 URL?
母版页支持后台代码,因此您可以在一个母版页中放入一些逻辑来决定应显示的内容。
我见过几个网站根据用户点击设置 cookie(以更改字体大小或页面宽度),然后根据这些 cookie 的值应用不同的 CSS 文件。如果不存在 cookie,则显示默认外观。
编辑:
这里的另一个想法是,如果您只是尝试切换 CSS,则将样式标记设置为在服务器上运行,并在运行时为其分配属性。这再次需要使用单个母版页,并将代码放在母版页的代码隐藏中,可能在 PreInit 事件处理程序中。
由于我从未实现过此解决方案,因此我不确定整个 <HEAD> 标记是否必须在服务器上运行。
<html>
<head id="Head" runat="server">
<style id="StylePlaceholder" runat="server" type="text/css"></style>
</head>
从基类继承所有页面,例如
public class PageBase : System.Web.UI.Page
{
public PageBase()
{
this.PreInit += new EventHandler(PageBase_PreInit);
}
void PageBase_PreInit(object sender, EventArgs e)
{
this.MasterPageFile = "~/MyMasterPage.Master";
}
}