设为首页 收藏本站
查看: 897|回复: 0

[经验分享] SharePoint 2010中的客户端AJAX应用——对话框显示详细信息页

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-9-24 09:50:23 | 显示全部楼层 |阅读模式
  本文是SharePoint 2010客户端AJAX应用系列的一部分。
  ASP.Net AJAX模板是一门全新的引人注目的客户端技术,允许开发者快速构建AJAX易于维护的交互式应用程序。由于ASP.Net AJAX模板和SharePoint 2010都支持oData协议,因此两者结合在一起将是一个强大的组合。
  SharePoint 2010 之所以可以带给人们Web 2.0的外观和感觉很大一部分要归功于其弹出式模式对话框的使用。为了进一步丰富上一篇中的AJAX应用,我们在每张卡片上挂接一个操作,打开一个对话框以便对该卡片做更细致的处理。在之前的使用SharePoint 2010模式对话框一文中,我们学习了如何在模式对话框中打开远端的页面,以及如何响应对话框确定或取消事件。本文中的模式对话框会更进一步,基于本地的HTML内容打开对话框。
  首先,我们在前文中做好的索引卡上添加一个编辑图标。我们将在其上挂接打开模式对话框的操作:



<div class="userStoryTitle">
{{ 标题 }}
<span class="userStoryButtons">
<a href="#">
<img src="/_layouts/images/edititem.gif" />
</a>
</span>
</div>

DSC0000.png
  
为了先简单测试一下打开对话框的效果,同时也复习一下前面学习的模式对话框的使用,我们编写如下的打开对话框代码:



function openDialog() {
var options = {
url: "http://www.cnblogs.com/Lists/UserStories/DispForm.aspx?Id=1",
width: 800,
height: 600,
title: "User Story",
};
SP.UI.ModalDialog.showModalDialog(options);
}

  
显然硬编码的URL中的参数id不是最佳做法,这里只是作为示范。结果看起来像这样:
DSC0001.png
  这是一个非常有用的技术,允许我们在不离开现有的SharePoint网页的情况下打开一个对话框,使用户可以直接浏览另一个网页。然而,在这里我们希望我们的应用程序中编辑的信息是在浏览器的内存里(通过ASP.Net AJAX模板存储数据)。该showModalDialog()函数可以支持这一方案,但要稍微复杂一些。

模式对话框方式打开本地HTML内容
  首先,我们需要一个HTML元素用于弹出。作为用来测试的一个初稿,我们使用如下的html内容:



<div id="userStoryDetails">
Hello World!
</div>

  
由于我们传递给showModalDialog()的options参数支持一个'html'参数来替代'url'参数,因此猜测可能看起来我们只需要简单地在openDialog中获取到userStoryDetails元素并作为选项传递即可。然而,这一做法有一个问题。默认SharePoint的showModalDialog()函数将销毁传递给它的DOM元素。结果是对话框只可以打开一次,再次打开就会失败。
  为了避免这种行为,我们可以在一个全局变量中缓存该DOM元素,而不是放在函数层中作为一个局部变量。代码如下所示:



var userStoryDetails;
Sys.onReady(function () {
userStoryDetails = document.getElementById("userStoryDetails");
...
});
function openDialog() {
var options = {
html: userStoryDetails,
width: 600,
height: 300,
title: "User Story",
};
SP.UI.ModalDialog.showModalDialog(options);
}
  
有了这个代码,我们就可以多次关闭和打开模式对话框了。结果如下所示:
DSC0002.png
接下来我们来处理对话框操作完成后的结果。在前面的文章中我们也介绍过做法。首先在对话框的代码中调用commonModalDialogClose(),然后在主窗口中实现回调函数,以便SharePoint在关闭弹窗时调用。
修改我们的userStoryDetails内容,增加调用commonModalDialogClose()的代码如下:



<div id="userStoryDetails">
<input
type="button"
value="确定"

class="ms-ButtonHeightWidth"
/>
<input
type="button"
value="取消"

class="ms-ButtonHeightWidth"
/>
</div>
  请注意commonModalDialogClose()第一个参数,是一个DialogResult。这个参数非常重要,因为我们的回调函数将通过此方法,区分不同的对话框关闭方式。例如,当用户点击在右上角的X时,SharePoint会传递DialogResult.cancel作为第一个参数。
  commonModalDialogClose()的第二个参数会直接作为回调函数的第二个参数进行传递。
  为了关闭对话框时对结果进行处理,我们可以为showModalDialog函数的options参数中增加一个dialogReturnValueCallback参数。结果如下:



function openDialog() {
var options = {
html: userStoryDetails,
width: 800,
height: 600,
title: "User Story",
dialogReturnValueCallback: onDialogClose
};
SP.UI.ModalDialog.showModalDialog(options);
}
function onDialogClose(dialogResult, returnValue) {
if (dialogResult == SP.UI.DialogResult.OK) {
alert('( ^_^ )/~~拜拜!');
}
if (dialogResult == SP.UI.DialogResult.cancel) {
alert(returnValue);
}
}

  
现在我们可以打开和关闭SharePoint模式对话框并处理结果。如果需要,我们还可以对模式对话框的options中的其他参数进行调整。例如的X,Y,allowMaximize,showMaximized和showClose。这方面的文档很少,希望MSDN上的这个页面在不久的将来能够更新。
  接下来,我们要正式进行对话框内容的编写。
  显示selectedData
  为了可以显示当前选定的项目,我们将需要将弹出对话框中的HTML绑定到当前选中的列表项。下面是一个最简单的例子:



<div id="userStoryDetails" class="sys-template">{{ 标题 }}</div>

  
注意其中sys-template类的使用。在上一篇博文中我们说过,任何dataView依附的元素都需要加上这个类。用于在页面加载时将该元素设为display:none,dataView显示时会将其设回到display:block。
  接下来,我们需要第二个dataView对象来绑定对话框中显示的HTML内容。



detailsDataView = Sys.query("#userStoryDetails").dataView().get(0);

  
注意,我们并没有像第一个dataView那样设置dataProvider或fetchOperation。原因是我们将绑定其data属性到主dataView的selectedData属性,如下所示:



$create(Sys.Binding, {
source: dataView,
path: "selectedData",
target: detailsDataView,
targetProperty: "data"
});
  selectedData 是DataView的一个特殊属性,代表当前选定的项目。现在离我们完成主-子关系的应用场景已经非常接近了。剩下的主要任务就是告诉主DataView什么时侯更新 selectedData。我们可以通过在主DataView的模板中的某个元素上添加sys:command="select"来完成该任务。添加到打开该模式对话框的按钮上应该最合乎逻辑:



<span class="userStoryButtons">
<a  href="#"  sys:command="select">
<img alt="edit" src="/_layouts/images/edititem.gif">
</a>
</span>

  
现在,我们完成了如下所示的逻辑:
DSC0003.png


显示主项对应的详细信息

  到目前为止,我们所显示的信息过于单薄了。在后面的博文中,我们会实现对字段内容的编辑和保存功能。本文中,我们仅仅再多加些只读字段。



<div id="userStoryDetails" class="sys-template">
<table class="ms-formtable" width="100%">
<tr>
<td class="ms-formlabel" width="190">标题:</td>
<td class="ms-formbody">{{ 标题 }}</td>
</tr>
<tr>
<td class="ms-formlabel" width="190">点数:</td>
<td class="ms-formbody">{{ 点数 }}</td>
</tr>
<tr>
<td colspan="2" nowrap>
<span>创建于 </span>
<span>{{ String.format("{0:yyyy-M-dd h:m tt}", 创建时间) }}</span>
<input type="button" name="OK" value="确定" class="ms-ButtonHeightWidth"
/>
<input type="button" name="Cancel" value="取消" class="ms-ButtonHeightWidth"
/>
</td>
</tr>
</table>
</div>

  关于上面的详细信息视图,有两处需要注意。其一,我们可以显示像点数这样的没有在主dataView出现过的字段(假设在列表中有这个字段)。之所以可以,是因为主dataView实际上默认情况下是下载了列表的所有字段。关于如何从相
  关的列表中获取数据也是我们在将来博文中要讨论的一个话题。
其二,我们处理日期时间的方式是如此简单。String.format是AJAX库提供的一个方法,可以用于格式化SharePoint提供的酷似C#/VB中的日期格式,使其变成读者可以接受的格式。以下是我们做好的新的详细信息视图:
DSC0004.png
  下面是至今为止整个应用程序的源代码:



<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UserStories.aspx.cs" Inherits="PreDemo.Layouts.PreDemo.UserStories" DynamicMasterPageFile="~masterurl/default.master" %>
<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
<style type="text/css">
.sys-template
{
display:none;
}
.userStoryBackground
{
background-image: url('Images/corkboard.png');
width:695px;
height:397px;
}
.userStoryCard
{
border: 1px solid #777777;
width: 206px;
height:124px;
cursor: move;
background-image: url('Images/blankcard.png');
margin:4px;
}
.userStoryDescription
{
padding: 5px;
line-height:1.2;
}
.userStoryTitle
{
font-weight: bold;
padding: 2px 5px 0px 5px;
}
.userStoryButtons
{
position: absolute;
right: 0px;
padding: 2px 2px 0 0;
}
.userStoryButtons img
{
border: 0 none;
}
</style>
<script src="/_layouts/Scripts/jQuery/jquery-1.4.1.js" type="text/javascript"></script>
<script src="/_layouts/Scripts/plugins/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script>
<script src="/_layouts/Scripts/MicrosoftAjax/Start.js" type="text/javascript"></script>
<script src= "/_layouts/Scripts/MicrosoftAjax/MicrosoftAjax.js" type="text/javascript"></script>
<script type="text/javascript">
Sys.require([
Sys.components.dataView,
Sys.components.openDataContext,
]);
var dataContext;
var dataView;
var userStoryDetails;
var detailsDataView;

Sys.onReady(function () {
userStoryDetails = document.getElementById("userStoryDetails");
dataContext = Sys.create.openDataContext({
serviceUri: "/_vti_bin/ListData.svc",
mergeOption: Sys.Data.MergeOption.appendOnly
});
dataView = Sys.query("#userStoriesList").dataView({
dataProvider: dataContext,
fetchOperation: "UserStories",
feachParameters: { orderby: '标题' },
autoFetch: "true",
rendered: onRendered
}).get(0);
detailsDataView = Sys.query("#userStoryDetails").dataView().get(0);
$create(Sys.Binding, {
source: dataView,
path: "selectedData",
target: detailsDataView,
targetProperty: "data"
});
});
function onRendered() {
$(".userStoryCard").draggable({
stop: onDragStop
});
}
function onDragStop(event, ui) {
var userStoryCard = ui.helper[0];
var selectedUserStoryJsonObject = dataView.findContext(userStoryCard).dataItem;
var newX = ui.position.left;
var newY = ui.position.top;
Sys.Observer.setValue(selectedUserStoryJsonObject, "X", newX);
Sys.Observer.setValue(selectedUserStoryJsonObject, "Y", newY);
dataContext.saveChanges();
}
function openDialog() {
var options = {
html: userStoryDetails,
width: 580,
height: 320,
title: "User Story",
dialogReturnValueCallback: onDialogClose
};
SP.UI.ModalDialog.showModalDialog(options);
}
function onDialogClose(dialogResult, returnValue) {
if (dialogResult == SP.UI.DialogResult.OK) {
}
if (dialogResult == SP.UI.DialogResult.cancel) {
}
}
</script>
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<div id="userStoryDetails" class="sys-template">
<table class="ms-formtable" width="100%">
<tr>
<td class="ms-formlabel" width="190">标题:</td>
<td class="ms-formbody">{{ 标题 }}</td>
</tr>
<tr>
<td class="ms-formlabel" width="190">点数:</td>
<td class="ms-formbody">{{ 点数 }}</td>
</tr>
<tr>
<td colspan="2" nowrap>
<span>创建于 </span>
<span>{{ String.format("{0:yyyy-M-dd h:m tt}", 创建时间) }}</span>
<input type="button" name="OK" value="确定" class="ms-ButtonHeightWidth"
/>
<input type="button" name="Cancel" value="取消" class="ms-ButtonHeightWidth"
/>
</td>
</tr>
</table>
</div>
<div id="userStoriesList" class="sys-template userStoryBackground" xmlns:sys="javascript:Sys">
<div  class="userStoryCard" sys:style="{{ 'left:'+X+'px;top:'+Y+'px;'}}">
<div class="userStoryTitle">
{{ 标题 }}
<span class="userStoryButtons">
<a  href="#"  sys:command="select">
<img alt="edit" src="/_layouts/images/edititem.gif">
</a>
</span>                           
</div>
<div class="userStoryDescription"><div>{{ 说明 }}</div>
</div>
</div>
</asp:Content>
<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
应用程序页
</asp:Content>
<asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server" >
我的应用程序页
</asp:Content>


总结

  我们已经了解了如何绑定一个详细信息DataView到当前选中的主DataView项目,并为不同的数据类型使用不同的格式设置。下一篇中我们将更新详细信息DataView,使其支持列表项的编辑。
  
  参考资料
  Client Side AJAX Applications in SharePoint 2010 - Part 5:Modal Dialogs
  Client Side AJAX Applications in SharePoint 2010 - Part 6:Master-Details

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-118060-1-1.html 上篇帖子: 在SharePoint中使用自定义的服务器控件(Web Control) 下篇帖子: SharePoint 2013 托管导航及相关配置 <二>
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表