为 SharePoint 创建应用程序时,应用程序的外观和感觉对其在用户中的成功起着至关重要的作用。我们需要问问自己,我们的 app 的观感是否和 SharePoint 的观感一致;使用我们的应用程序的体验是否符合 SharePoint 的标准机制?
同样,应用的外观和感觉非常重要。如果我们的应用程序具有与 SharePoint 一致的外观和感觉,它将提供更好的用户体验。
您可以在 SharePoint 应用程序中引用 SharePoint 网站的样式表。有趣的是,如果您更改了 SharePoint 网站的主题或样式表,它会自动在应用程序中应用新的样式表,而不会更改应用程序中的样式引用表。
这将继承所有样式,您可以使用 SharePoint 样式表中的所有类和选择器,然后应用与 SharePoint 网站一致的样式。
这将继承所有样式,您可以使用 SharePoint 样式表中的所有类和选择器,然后应用与 SharePoint 网站一致的样式。
图 31:使用默认样式
<h1 class="ms-core-pageTitle"> H1 with ms-core-pageTitle class</h1>
<h1 class="ms-accentText"> H1 with ms-accentText class</h1>
<h2 class="ms-accentText"> H2 with ms-accentText class</h2>
<div>
<h2 class="ms-webpart-titleText"> H2 with ms-webpart-titleText
class</h2>
<a class="ms-commandLink" href="#"> Anchor with ms-commandLink
class</a>
<br />
<p>
This sample shows you how to use some of the classes defined
in the SharePoint website's style sheet.
</p>
</div>
基本上有三种不同的方法来引用 SharePoint 样式表,具体取决于我们正在开发的应用程序类型:
- 使用应用程序的默认母版页:在这种情况下,我们只有在制作 SharePoint 托管的应用程序时才能使用这种技术,因为母版页已经是对您的 SharePoint 网站样式表的引用。
- 引用并使用 chrome 控件:在这种情况下,我们可以使用一个客户端控件,由 SharePoint 提供,允许我们在半自动模式下应用类似于 SharePoint 默认母版页的布局。它通常在您认识到应用程序托管的提供程序时使用,因为它们不能直接使用 SharePoint 母版页。我们将在后面解释这个模式的更多细节。
- 手动引用样式表:所有情况下都可以手动引用样式表文件,比如在制作页面的时候不想使用 SharePoint chrome 控件的母版页。
我们可以通过添加一个标记链接并创建一个包含 web 主机 URL 的 href,动态检索它来手动引用样式表。这很好,因为我们希望直接在服务器端呈现标签的链接,在正文中使用之前将它放在页面上:
<link rel="stylesheet"
href="{host web URL}/_layouts/15/defaultcss.ashx" />
或者,我们可以动态加载客户端标签链接,总是引用 web 主机,如下所示:
(function () {
var hostWebUrl;
var ctag;
// Get the URI decoded app web URL.
var hostWebUrl = decodeURIComponent(
getQueryStringParameter("SPHostUrl" ));
// Get the ctag from the SPClientTag token.
var ctag = decodeURIComponent(
getQueryStringParameter("SPClientTag"));
// Create defaultcss.ashx URL.
var defaultCssUrl = hostWebUrl +
"/_layouts/15/defaultcss.ashx?ctag=" + ctag;
// Dynamically create the link element.
var link = document.createElement("link");
link.setAttribute("rel", "stylesheet" );
link.setAttribute("href", defaultCssUrl);
// Append the link element in the document head.
var head = document.getElementsByTagName("head" );
head[0].appendChild(link);
})();
// Function to retrieve a query string value
function getQueryStringParameter(paramToRetrieve) {
var params;
var strParams;
params = document.URL.split("?")[1].split("&" );
strParams = "";
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}
当链接加载到页面中时,此方法唯一的问题就出现了。由于页面的 HTML 显示了 CSS 实际链接到的内容,因此页面将是页面上的一盏明灯,因为样式仅在 CSS 实际加载时应用。解决这个问题的一种技术是隐藏 HTML 页面的主体,并且只在加载完 CSS 时显示它。
如前所述,该技术允许您在不使用母版页的情况下创建与 SharePoint 非常相似的布局。
使用 chrome 控件为 SharePoint 托管的应用程序或不能以任何方式在 SharePoint 中使用母版页的提供者托管的应用程序创建 HTML 页面非常方便。
图 32:运行中的 Chrome 控件
chrome 控件在页面顶部包含一个栏,其中包含一个名为“返回站点”的链接,该链接允许您返回到 web 主机。在右侧,“设置”菜单和“帮助”按钮是可见的,因为它们是传递给配置的。
另一个优点是,我们会自动链接到我们的 SharePoint 网站的样式,允许我们使用所有基本的样式。
为了使用它,我们需要编写将由客户端页面加载执行的 JavaScript 代码。
我们需要引用一个名为 SP 的文件。在 SharePoint 里面 UI.Controls.js 然后写代码初始化。
以下是放入页面的假设正文内容:
<body style="display : none">
<!-- Chrome control placeholder -->
<div id="chrome_ctrl_placeholder"></div>
<div style="margin : 0px 20px 0px 20px">
<!-- The chrome control also makes the SharePoint Website -->
<!-- style sheet available to your page. -->
<h1 class="ms-accentText"> Title</h1>
<h2 class="ms-accentText"> Subtitle</h2>
<div id="MainContent">
This is the page's main content.
</div>
</div>
</body>
标识为 chrome_ctrl_placeholder 的 div 用作占位符来保存 chrome 控件的 HTML 呈现。
为了加载和初始化 chrome 控件,我们可以编写一些这样的 JavaScript:
<script src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"
type="text/javascript"></script>
<script src="../Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
"use strict";
$(document).ready(function () {
//Get the URI decoded URL.
var hostweburl = decodeURIComponent(
getQueryStringParameter("SPHostUrl"));
var scriptbase = hostweburl + "/_layouts/15/";
// Load the js file and continue to renderChrome function
$.getScript(scriptbase + "SP.UI.Controls.js" , renderChrome)
});
//Function to prepare the options and render the control
function renderChrome() {
// Create options object to initialize Chrome control
var options = {
"appIconUrl" : "img/AppIcon.png" ,
"appTitle" : "Chrome Control",
"appHelpPageUrl" : "help.html?"
+ document.URL.split("?")[1],
"onCssLoaded" : "chromeLoaded()" ,
"settingsLinks" : [
{
"linkUrl" : "link1.html?"
+ document.URL.split("?")[1],
"displayName" : "Link 1"
},
{
"linkUrl" : "link2.html?"
+ document.URL.split("?")[1],
"displayName" : "Link 2"
}
]
};
// Create new chrome control.
var nav = new SP.UI.Controls.Navigation(
"chrome_ctrl_placeholder" , options);
// Show chrome control
nav.setVisible(true);
}
// Callback for the onCssLoaded event
function chromeLoaded() {
// When the chrome control has loaded, display the page body.
$("body" ).show();
}
// Function to retrieve a query string value.
function getQueryStringParameter(paramToRetrieve) {
var params =
document.URL.split("?")[1].split("&" );
var strParams = "" ;
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}
</script>
此示例涉及动态加载、初始化脚本,然后,当我们自动加载 SharePoint 样式表时,它将对页面主体可见。
在创建应用程序时,我们可以选择用户使用应用程序本身的几种方式。
总共有三种模式:
- 沉浸式整页
- 客户端网页组件(应用程式组件)
- 自定义操作
沉浸式整页是默认模式;每个应用程序必须包含至少一个也是主页的页面。当您点击应用程序时,SharePoint 会将请求重定向到应用程序的主页,这实际上是应用程序的入口点。
此模式允许您通过使用应用程序来实现 web 部件的概念。它也被称为应用程序部分。一旦安装了应用程序,如果该应用程序有部分,用户可以选择它们,并通过从应用程序部分目录中选择它们将其插入到您的 SharePoint 页面中。
创建应用程序部件很简单。Visual Studio 提供了一个名为“网页组件客户端”的项目项。
图 33:添加客户端 web 部件
此时,Visual tudio 将提示您询问是要创建新页面还是选择以前创建的页面:
图 34:创建新的客户端 web 部件页面
这是因为应用程序的一部分是一个 HTML 页面,它将显示在托管它的页面的 IFrame 中。
一旦添加到项目中,我们可以看到页面已经在模块“页面”下创建,并且包含应用程序部分必要配置的项目新项目已经添加。
图 35:应用程序部分文件
在 Element.xml 中,我们可以根据我们可以创建的名称、标题、描述、大小和属性来配置我们的应用程序部分。这允许用户像配置经典 web 部件一样配置应用部件。
属性通过查询字符串传递到页面,使用的约定是将属性的名称放在页面的 URL 中,名称前后带有“_”。
例如,如果我们想创建一个名为“Property1”的字符串类型的属性,我们写的是:
<?xml version= "1.0 " encoding= "utf-8 "?>
<Elements XMLns= "http://schemas.microsoft.com/sharepoint/ ">
<ClientWebPart Name= "AppPart "
Title= "AppPart Title "
Description= "AppPart Description "
DefaultWidth= "300 "
DefaultHeight= "200 ">
<!-- Content element identifies the location of the page that
will render inside the client web part
Properties are referenced on the query string using the
pattern _propertyName_
Example: Src="~appWebUrl/Pages/ClientWebPart1.aspx
?Property1=_property1_" -->
<Content Type= "html " Src= "~appWebUrl/Pages/AppPart.aspx
?{StandardTokens}&_property1_" />
<!-- Define properties in the Properties element.
Remember to put Property Name on the Src attribute of the
Content element above. -->
<Properties>
<Property Name= "Property1 "
Type= "string "
DefaultValue= "Default Value "
PersonalizationScope= "shared "
RequiresDesignerPermission= "false "
WebBrowsable= "true "
WebDisplayName= "Property 1 "
WebCategory= "Custom Property "
WebDescription= "Custom Property called Property 1"/>
</Properties>
</ClientWebPart>
</Elements>
我们可以创建以下属性类型:
- 线
- (同 Internationalorganizations)国际组织
- 布尔代数学体系的
- 列举型别
为了检索属性的值,只需转到页面检索查询字符串中的相应值。
在本例中,我们在 SharePoint 托管的设计类型中创建了一个应用程序部件,但同样的示例也适用于提供者托管的项目。在这种情况下,页面不是本地的,而是一个远程 web 应用程序。
Visual Studio 创建的页面是一个。包含特殊 SharePoint 控件的 aspx 页面:
<WebPartPages:AllowFraming ID="AllowFraming" runat="server" />
此控件通过从页面响应中删除 HTTP 头 X-Frame-Options,使 SharePoint 能够在 IFrame 中承载此页面。否则,就不可能在 IFrame 中使用该页面。
在同一页面上,我们看到有一个 JavaScript,它允许动态加载 corev15.css 文件来合并 SharePoint foundation 样式:
if (hostUrl == '' ) {
document.write('<link rel="stylesheet"
href="/_layouts/15/1033/styles/themable/corev15.css" />' );
}
部署应用程序后,我们可以通过编辑页面,然后从目录中选择应用程序部件来添加我们的应用程序部件:
图 36:插入应用程序部分
一旦您选择并插入页面(之前已进入编辑状态),我们的应用程序部分将显示以下内容:
图 37:页面上插入的应用程序部分示例
如果我们需要调整应用程序部分的大小以适应其内容,您必须使用如下机制:
function Resize() {
var width = 500;
var height = 300;
var senderId = null ;
var hostUrl = null ;
if (window.parent == null )
return ;
// Extracts the host URL and sender ID.
var params = document.URL.split("?")[1].split("&" );
for (var i = 0; i < params.length; i = i + 1) {
var param = params[i].split("=");
if (hostUrl == null ) {
hostUrl = decodeURIComponent(param[1]);
}
if (i == (params.length - 1))
senderId = decodeURIComponent(param[1]);
}
// *********************************************
// Use the postMessage api to resize the App part.
var message = "<Message senderId="
+ senderId + " >"
+ "resize(" + widthSelected
+ "," + height
+ ")</Message>" ;
window.parent.postMessage(message, hostUrl);
}
通过调用 resize()函数,它基本上允许我们从查询字符串中提取必要的参数,然后我们可以使用 postMessage API 发送一条以这种方式格式化的消息:
<message senderId={SenderId}> resize({width}, {height})</message>
因此,您可以通知宿主页面以指定的大小调整大小。
另一种与应用程序的交互是自定义操作。应用程序有两种类型的自定义操作:
- 功能区自定义操作
- 菜单项自定义操作
在第一种情况下,我们可以在功能区栏上插入一个具有一系列可能配置的按钮。在第二种情况下,我们可以在列表中菜单项的上下文中插入一个自定义操作:
图 38:自定义功能区操作
图 39:菜单项自定义操作
由于图 40 所示的可用项目模板,我们可以添加自定义操作和功能区列表项自定义操作:
图 40:添加自定义操作
在这两种情况下,我们都必须配置包含我们插入的自定义项目的站点类型,或者一组基本参数,如标签和登录页。在自定义功能区操作的情况下,可以指定功能区控件内的位置,如图 41 所示。
图 41:菜单项自定义操作设置
图 42:功能区自定义操作设置
每个自定义操作都会创建将成为核心页面的目标 URL,以及一系列查询字符串参数,如下例所示:
?HostUrl={HostUrl}&Source={Source}&ListURLDir={ListUrlDir}&ListID={ListId}&ItemURL={ItemUrl}&ItemID={ItemId}
这样,在目标页面中,我们将能够通过查询字符串参数进行恢复,如主机、列表标识、项目选择标识等。
在本章中,我们学习了如何从 UX 的角度设计我们的应用程序,无论我们是创建 SharePoint 托管的还是提供者托管的应用程序。
我们了解到,应用程序部分的使用促进了我们的应用程序在将使用它的 SharePoint 网站中的集成,而自定义操作的使用允许我们插入由应用程序本身管理的扩展点列表级别或库。