天道酬勤,学无止境

How to dynamically switch PageLayout and MasterPage of SharePoint Publishing page?

To improve both the editing and displaying experience of SharePoint WCM Publishing pages I would like to be able to switch to a special set of Masterpage/PageLayout when in edit mode.

So in /_catalogs/masterpage I want to have:

MyMasterpage.master - masterpage for display mode MyMasterpage-edit.master - masterpage for edit mode, only use if available MyPageLayout.aspx - pagelayout for display mode MyPageLayout-edit.aspx - pagelayout for edit mode, only use if available

When I create a new publishing page in the Pages library, I select the MyPageLayout page layout.

When rendering the page I would like to detect if I'm in Edit of Display mode, just like the server control does. This control executes the following code to determine the render mode:

private void calculateShouldRender()
{
    SPControlMode contextualFormModeFromPostedForm = ConsoleUtilities.GetContextualFormModeFromPostedForm();
    if ((SPControlMode.Display == contextualFormModeFromPostedForm) && (PageDisplayMode.Display == this.PageDisplayMode))
    {
        this.shouldRender = true;
    }
    else if ((SPControlMode.Edit == contextualFormModeFromPostedForm) && (PageDisplayMode.Edit == this.PageDisplayMode))
    {
        this.shouldRender = true;
    }
    else
    {
        this.shouldRender = false;
    }
    this.Visible = this.shouldRender;
}

If the render mode is Edit, I want to switch to the MyMasterpage-edit.master materpage and the MyPageLayout-edit.aspx pagelayout.

I could make a big switch in the masterpage and pagelayout controlled by server controls, but I would like to split resposibilities. A SharePoint Analist can create optimal edit mode pages, and a front end developer can create clean and beautiful display mode pages without all the editing clutter.

Any ideas on how to accomplish this? Masterpage switching does not seem the problem, I once wrote a blogpost on this. The difficult thing seems the switching of the page layout.

评论

I think you would be fighting SharePoint if you continue down that route, I fear it would also become something of a support nightmare as it becomes less clear where problems lie, or remembering to make changes in both (or all four!) places when something is updated.

You can have controls appear or hide depending on the editmode of a page so what is shown to the user is totally different but all the code for a page is still in one place.

Investigate the editmodepanel.

<publishingwebcontrols:editmodepanel ID="Editmodepanel1" runat="server">
   <link id="Link2" rel=Stylesheet href="<% $SPUrl:~sitecollection/EditMode.css %>" runat="server" type="text/css" />
</publishingwebcontrols:editmodepanel>

I realise that is not quite what you asked... but I find fighting SharePoint is a losing battle you just have to work with its 'way'.

I once wrote a feature to switch page-layouts depending on different criteria. The difference was, that the page-layout was changed during site-creation, not in view or edit mode. The code to change the page-layout is as follows:

    private void SetPageLayout(SPWeb web, string pageName, string pageLayoutName)
    {
        PageLayout layout = null;
        PublishingPage page = null;
        SPFile pageFile = null;
        bool checkedOut = false;

        try
        {
            PublishingWeb publishWeb = PublishingWeb.GetPublishingWeb(web);
            // verify that the requested pageLayout is available
            foreach (PageLayout pl in publishWeb.GetAvailablePageLayouts())
            {
                if (pl.Name.Equals(pageLayoutName, StringComparison.OrdinalIgnoreCase))
                {
                    layout = pl;
                    break;
                }
            }
            // got my layout
            if (layout != null)
            {
                page = null;
                foreach (PublishingPage pubPage in publishWeb.GetPublishingPages())
                {
                    if (pageName == pubPage.Name)
                    {
                        page = pubPage;
                        break;
                    }
                }
                // got my page
                if (page != null)
                {
                    pageFile = page.ListItem.File;

                    page.CheckOut();
                    checkedOut = true;

                    page.Layout = layout;
                    page.Update();

                    page.CheckIn("changed the page-layout to " + pageLayoutName);
                    checkedOut = false;

                    pageFile.Publish("");
                    // If required, approve the page
                    try
                    {
                        pageFile.Approve(string.Empty);
                    }
                    catch
                    {
                        // Page doesn't need to be approved
                    }
                }
            }
        }

My text was too long for the comment box, so I answer on Aiden as if it is an answer, but my question remains!

Hi Aidan, I see SharePoint as a platform where you can build your solutions on. And I think that the WCM solution built by Microsoft on top of the platform is weak. I know my way is not directly the SharePoint standard way, but the standard way just does not work. Combining edit and display mode leads to (pick your choice): - standard SharePoint publishing sites that all look alike but work ok in edit mode - a site that is very editable but very basic in its appearance - a great looking site in display mode, that is almost impossible to edit We have a lot of clashes between the stylesheets needed in display mode with the MOSS WCM stylesheet. We did write all kinds of compensating stylesheets to get it working, but it is a pain in the ***. It is a major flaw to inject code with styles in your page to make editing possible, this should have done completely outside the page you are editing. In an iframe for example which can be displayed as a floating window on top of the page you are editing. But this is not the case. And then I didn't even mention the issues you have when you have tabs or an accordion control on your page.

We are targeting really interactive web 2.0 sites where a lot of content management must be done. Getting editing mode right in the SharePoint way just does not work.

An optimal editing experience is key. So why not use the masterpage and pagelayout optimized for editing so all editable elements are reachable in a clear and consistent way. But then you still need the display mode. This could be done using a complete separate site that just uses the data produced in SharePoint. This can be an ASP.NET site, or if you want full control over the html MVC could be used. I don't at to go that way, because but has a lot of implications in navigation, security, reuse of controls, use of web parts etc.

I think you get best of both worlds if a masterpage/pagelayout is used that is optimized for editing, and another couple of masterpage/pagelayout is used for display only with a minimal set of code in the pagelayout.

So.. keep the answers coming please!

Surely that would require subclassing Microsoft.SharePoint.Publishing.PublishingLayoutPage and use that to render the contents of the actual PublishingLayoutPage required depending on the "edit mode".

How to get a master page changed...ek.

Trying to bend The SharePoint to your will again? ;)

I feel your pain. I'm using 2 ways to get similar behaviour:

A container control to condionally render parts of pages, I think like you suggested. Initially I needed it to hide parts of the page when some field had a specific value so no html was rendered. See wrapper controls. The control itself is very simple, it needs a [ParseChildren(false)] on its class and the render method does not call the base render if the condition is not met. You can extend this to display en entirely different page to an editor and designer although it would all still live in the same page. I guess you could strip out the part used by the analist and put it in its own usercontrol but thats not very maintainable.

Secondly, the form page, e.g. "/Pages/Forms/EditForm.aspx?ID=1", gives a clean view of all the fields on a publishing page.. no design to get in the way. (I use a control on all page layouts that provides 1 click access to this and the current pages library and shows the content type and page layout used. Quite useful when building WCM sites.)

The definitive answer to this question is now "baked" into a product which we call DualLayout for SharePoint! Our approach solves all your SharePoint WCM design nightmare:

  • Introduce an additional view for the end user, besides the WCM edit and display views
  • Never have clashes between SharePoint styles and your own styles
  • Make lean and mean "view" master pages and page layouts that don't interfer with the WCM master pages and page layouts
  • Make super-light pages for the end-user, remove all SharePoint specific page clutter
  • Improve the performance of the pages because we only have a minimal set of controls to render in the end user view

Check it out at http://www.macaw.nl/Het+Bedrijf/Producten/Macaw+DualLayout+for+SharePoint.aspx, see the blog posts in the blog roll of that page for detailed background information.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Create a webpart page with an webpart with in it programmatically
    I want to create several webpart pages (programmatically) with custom web parts in it. I have searched the internetz but couldn't find anything that I could get to work. Here is my code so far (where I create a welcome page, not a webpart page): using (SPSite site = new SPSite("http://v99-sp-public/")) { using (SPWeb web = site.OpenWeb()) { PublishingSite pSite = new PublishingSite(site); SPContentType ctype = pSite.ContentTypes["Welcome Page"]; PageLayoutCollection pageLayouts = pSite.GetPageLayouts(ctype, true); PageLayout pageLayout = pageLayouts["/_catalogs/masterpage/welcomesplash.aspx"]
  • How do I use Paul Irish's Conditional comments in a SharePoint 2010 master page
    I want to use Paul Irish's Conditional comments from the Boilerplate HTML template: <!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]--> <!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]--> <!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]--> <!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]--> <!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"> <!--<![endif]--> in a SharePoint 2010 masterpage. I have read 'conditional comments don’t always work so well in SP2010'. (not sure what that means!) The advice is to use: <SharePoint
  • AngularJS Controller execute twice
    I must add I am working on Sharepoint 2013, visual web part. my ascx: <%@ Control Language="C#" Inherits="SharePoint.BLL.UserControls.VODCatalog, SharePoint.BLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=81fc048468441ab3" %> <%@ Register TagPrefix="SPWP" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <div
  • 是否可以动态扩展类?(Is it possible to extend a class dynamically?)
    问题 我有一个类,我需要根据标准来扩展不同的类(最多数百个)。 PHP中是否可以通过动态类名扩展类? 我认为这将需要一种方法来指定带有实例化的扩展。 有想法吗? 回答1 我认为无法动态扩展类(但是,如果我错了,我很乐意看到它是如何完成的)。 您是否考虑过使用复合模式(http://en.wikipedia.org/wiki/Composite_pattern,http://devzone.zend.com/article/7)? 您可以动态地组合另一个类(甚至是多个类-这通常被用作多重继承的替代方法),以将父类的方法/属性“注入”到子类中。 回答2 虽然这仍然是不可能的,而且也不完全是您的答案,但我需要同样的东西,并且不想使用eval,monkey-patching等。因此,我通过在条件中扩展它来使用默认类。 当然,这意味着如果您要扩展100个类,则需要使用另一个扩展操作添加100个条件,但是对我来说,这看起来像是正确的方法。 <?php if(class_exists('SolutionClass')) { class DynamicParent extends SolutionClass {} } else { class DynamicParent extends DefaultSolutionClass {} } class ProblemChild extends
  • 解析器错误消息:无法加载类型'webmarketing'(Parser Error Message: Could not load type 'webmarketing')
    问题 完成Web应用程序并在线发布后,无论我如何尝试都遇到以下错误,请记住它应在本地运行... 解析器错误消息:无法加载类型'webmarketing'。 我尝试了该解决方案,尽管据称我正在做与该解决方案相同的工作,但是我仍然面临着同样的问题... ASP.NET分析器错误无法在后面加载代码 这是背后的代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace webmarketing { public partial class Masterpage : System.Web.UI.MasterPage { protected void Page_Load(object sender, EventArgs e) { string admin = (string)Session["Admin"]; if (string.IsNullOrEmpty(admin)) { logout.Visible = false; } else { } } } } 回答1 在我将CodeBehind更改为CodeFile之前,我遇到了同样的问题,它的工作原理
  • How to change Action attribute of the aspnetForm on MasterPage dynamically
    We are trying to modify the Action attribute of the main ASP.NET form in the master page dynamically. The page has a radio button, user selects one of the options and clicks on submit, on postback, based on the selection the Form's action attribute should be set and the form should be submitted again automatically. We were trying to use JavaScript for the same. document.forms[0].action = "option1.aspx"; document.forms[0].submit(); But this doesn't seem to be working, there is no impact on the action attribute. if we don't use a master page, this can be achieved easily by using this.Form.Action
  • JavaFX8 Print API:如何正确设置可打印区域(JavaFX8 Print API : how to set correctly the Printable area)
    问题 在我的javafx应用程序中,我使用JavaFX 8打印API来打印节点,尽管我已经用A4纸设置了pageLayout,但是却遇到了打印区域的问题....这是我的代码: public static void printNode(final Node node) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Printer printer = Printer.getDefaultPrinter(); PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, 0,0,0,0 ); PrinterJob job = PrinterJob.createPrinterJob(); if (job != null && job.showPrintDialog(node.getScene().getWindow()) ) { boolean success = job.printPage(pageLayout, node); if (success) { job.endJob(); } } 这是我要打印的节点的快照
  • 如何在母版页菜单中突出显示活动页?(How to highlight active page in a masterpage menu?)
    问题 我在masterpage (在ASP.NET网站中)有一个菜单,并且我想在母版页菜单和子菜单中突出显示活动页。 HTML: <ul id="nav" class="sf-menu"> <li class="current-menu-item"><a href="index.html">Home</a></li> <li><a href="page.html">menu-2</a> <ul> <li><a href="page-full.html">full</a></li> <li><a href="page-features.html">featurs</a></li> <li><a href="page-typography.html">typography</a></li> </ul> </li> </ul> CSS: #nav>li.current-menu-item>a, #nav>li.current_page_item>a{ color: #fe8300; } 提前致谢。 回答1 终于我用jQuery解决了我的问题: var str=location.href.toLowerCase(); $("#nav li a").each(function() { if (str.indexOf($(this).attr("href").toLowerCase()) >
  • 服务器响应为:5.7.0必须首先发出STARTTLS命令。 i16sm1806350pag.18-gsmtp(The server response was: 5.7.0 Must issue a STARTTLS command first. i16sm1806350pag.18 - gsmtp)
    问题 我正在尝试使用gmail发送邮件,但出现了一个异常,即The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first. i16sm1806350pag.18 - gsmtp The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first. i16sm1806350pag.18 - gsmtp 我编写的用于发送邮件的代码是: MailMessage mail = new MailMessage(); mail.To.Add(txtEmail.Text.Trim()); mail.To.Add("Secondry@gmail.com"); mail.From = new MailAddress("mysendingmail@gmail.com"); mail.Subject = "Confirmation of
  • JavaFX : Image getting scaled to 25% and then getting printed.
    I am trying to print an image using JavaFX api's. Unfortunately, it is cutting a part of the image, approximately 25% and then stretching that to the entire A4 page, and printing it. What am I doing wrong with the print code. How can I instruct to fit the image to page for printing, no matter what the printer is. Kindly let me know. Code : public void printThis() { System.out.println("I was called"); // note you can use overloaded forms of the Image constructor // if you want to scale, etc String path = "resources/img/printouts/image.png"; Image image = new Image(getClass().getResource(path)
  • VS2012中无法识别的标记前缀或设备筛选器“ asp”(Unrecognized tag prefix or device filter 'asp' in VS2012)
    问题 我最近安装了VS2012,并处理了以前用于VS2010的工作项目。 我从来没有遇到过问题,VS2010不能识别asp前缀标签,而VS2012可以。 我尝试删除下面的ReflectedSchemas文件夹 C:\ Users [用户名] \ AppData \ Roaming \ Microsoft \ VisualStudio \ 11.0 \ 但仍然无法正常工作。 有人在VS2012中遇到此问题吗? 回答1 从解决方案资源管理器关闭并重新打开文件(.aspx文件不是解决方案)在Visual Studio 2015中对我有用。在尝试任何其他操作之前,您可以尝试一下。 回答2 您是否在Web.Config中碰到了类似这样的内容: <pages> <controls> <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0
  • Choose dynamically at runtime which version of a .dll to use
    I'm working on a utility for SharePoint. It's an app that works for both SharePoint 2007 and 2010. When I have a reference to the 12.0.0.0 version of the SharePoint.dll, the app works for SharePoint 2007, but not for 2010. If I reference version 14.0.0.0 of the dll, then the app works great for 2010, but not for 2007. I can easily tell which .dll that I need to use by looking on the file system with the following code, checking for 12 in the path (SharePoint 2007) or 14 (SharePoint 2010). System.IO.File.Exists( Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + @"
  • 为什么“”被注入到我的HTML中?(Why is “​” being injected into my HTML?)
    问题 编辑:您可以在这里看到问题(在源代码中查找)。 EDIT2:有趣的是,这不是问题。 仅通过控制台(以及Firebug)。 我在名为test.html的文件中具有以下标记: ​<!DOCTYPE html> <html> <head> <title>Test Harness</title> <link href='/css/main.css' rel='stylesheet' type='text/css' /> </head> <body> <h3>Test Harness</h3> </body> </html> 但是在Chrome浏览器中,我看到了: <!DOCTYPE html> <html> <head> </head> <body> "​ " <title>Test Harness</title> <link href='/css/main.css' rel='stylesheet' type='text/css' /> <h3>Test Harness</h3> </body> </html> 看起来&#802是一个零宽度的空间,但是是什么原因引起的呢? 我正在使用具有UTF-8编码的Sublime Text 2和带有Jinja2的Google App Engine(但Jinja只是在加载test.html )。 有什么想法吗? 提前致谢。 回答1 这是问题的根源
  • SAAS产品灰度技术深入浅出
    灰度发布,即AB test。是发现、调整产品问题的重要手段,通过灰度发布可以控制产品迭代过程中的影响度。纷享销客是用于移动办公和销售管理的办公软件,其产品形态主要体现在网页,手机APP以及PC客户端。以下将描述纷享销客在网页端实现灰度发布过程中的手段和原理,供大家学习参考:1. 服务端模板配置查看http://www.fxiaoke.com/XV/Home/Index网页源码<link rel="stylesheet" href="//www.fspage.com/html6/base-dist/assets/style/all.css" />其中静态资源的引用中有"html6"这个字符串,服务端将根据登陆用户或企业的不同,在输出服务端模板内容时,动态改变路径为html6,html5或html4等等,从而影响用户最后访问的功能。2. nginx流量分发举个例子,如果产品线上服务器使用nginx,可以在nginx这一层,根据当前用户cookie或者来源ip,动态分配接口流量切换至a/b服务,静态文件将流量切换至a/b路径或主机,这个方案非常适合无登陆状态的产品灰度发布。3. 前端脚本动态分发 对于无法使用1,2方案的场景,只能依靠前端在访问入口页面a.html时,前端与业务接口通信,判断是否进行灰度,然后前端分发至a.html或a-gray.html页面。4. ajax接口分发路由
  • 打印JavaFx TableView的内容(Print contents of JavaFx TableView)
    问题 我正在寻找一种打印JavaFX TableView内容的方法。 我了解到JavaFX尚无打印功能(令人失望)。 我发现了一些有关以WebView的屏幕截图为例并将其打印为图像的信息。 是否可以使用“表格”视图执行类似的操作。 如何处理具有许多数据的表上的多个页面。 谢谢你的帮助 回答1 打印API出现在fx8.0中。 它可以打印节点。 您可以使用javafx.print.PrinterJob类创建打印机作业。 但是它只打印适合打印页面的区域,而不打印您在屏幕上的区域。 因此,您需要手工制作适合节点的页面(缩放,平移等)。 这是简单的打印示例: PrinterJob printerJob = PrinterJob.createPrinterJob(); if(printerJob.showPrintDialog(primaryStage.getOwner()) && printerJob.printPage(yourNode)) printerJob.endJob(); 回答2 剪出您想要的区域 Rectangle rect = new Rectangle(0,0,dataDisplayAreaAnchorPane.getWidth(),dataDisplayAreaAnchorPane.getHeight()); dataDisplayAreaAnchorPane
  • JavaFX8 Print API : how to set correctly the Printable area
    In my javafx application , I'm using JavaFX 8 printing API to print a node , i am getting problem of the printing area , despite i have set the pageLayout with A4 paper .... here is my code : public static void printNode(final Node node) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Printer printer = Printer.getDefaultPrinter(); PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, 0,0,0,0 ); PrinterJob job = PrinterJob.createPrinterJob(); if (job != null && job.showPrintDialog(node.getScene().getWindow(
  • masterpage initializeculture no suitable method found to override error?
    I'm trying to develop a MultiLanguage web site using ASP.NET with C# My problem is: I want to make my MasterPage support switching among languages, but when i put the "InitializeCulture()" inside the masterpage.cs, I got this error. this is my code: public partial class BasicMasterPage : System.Web.UI.MasterPage { protected void Page_Load(object sender, EventArgs e) { } protected void Calendar1_DayRender(object sender, DayRenderEventArgs e) { if (e.Day.IsToday) { e.Cell.Style.Add("background-color", "#3556bf"); e.Cell.Style.Add("font-weight", "bold"); } } Dictionary<string, System
  • IE11中的“对象不支持此属性或方法”错误(“Object doesn't support this property or method” error in IE11)
    问题 我收到错误 严重错误:对象不支持此属性或方法addeventlistener 在IE 11浏览器中访问InfoPath表单页面(使用启用InfoPath的列表表单,例如displayifs.aspx)时。 此错误特定于IE 11,该页面已在IE 10及更低版本中正确打开。 根据此MSDN帖子,IE 11支持addEventListener。 有人对此有想法吗? 回答1 不幸的是,这破坏了其他事情。 这是我在另一个似乎对我有用的网站上找到的修复程序: 我想说将X-UA-Compatible保留为"IE=8"然后将以下代码添加到母版页的底部: <script language="javascript"> /* IE11 Fix for SP2010 */ if (typeof(UserAgentInfo) != 'undefined' && !window.addEventListener) { UserAgentInfo.strBrowser=1; } </script> 这修复了core.js中的一个错误,该错误错误地计算了将IE11设置为UserAgentInfo.strBrowse=3错误,从而支持addEventListener 。 除此以外,我不确定其他细节,但保持IE = 8并使用此脚本的组合对我来说是可行的。 直到我找到下一个IE11 / SharePoint
  • Generating the Shortest Regex Dynamically from a source List of Strings
    I have a bunch of SKUs (stock keeping units) that represent a series of strings that I'd like to create a single Regex to match for. So, for example, if I have SKUs: var skus = new[] { "BATPAG003", "BATTWLP03", "BATTWLP04", "BATTWSP04", "SPIFATB01" }; ...I'd like to automatically generate the Regex to recognize any one of the SKUs. I know that I could do simply do "BATPAG003|BATTWLP03|BATTWLP04|BATTWSP04|SPIFATB01", but list of SKUs can be quite lengthy and I'd like to compress the resulting Regex to look like "BAT(PAG003|TW(LP0(3|4)|SP04))|SPIFATB01" So this is a combinatorics exercise. I
  • How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
    I'm just learning JSF 2 thanks to this site I had learned a lot in such a short time. My question is regarding how to implement a common layout to all my JSF 2 pages and have only the content part of the page refresh not the whole page whenever I click a link/menu from a different panel. I am using the Facelets approach it does what I want except that each time I click a link from a panel (e.g. menu items from left panel) the whole page is refreshed. What I am looking for is a way to refresh only the content part of my page. To illustrate this below is my target pagelayout. Did not post my