2.jpg ( 156.68 K)
-
2008-9-3 13:06:20
3.jpg ( 49.71 K)
-
2008-9-3 13:06:20
5.jpg ( 106.76 K)
-
2008-9-3 13:06:20
具体的范例请见我的BLOG...
blog.lickies.cn
现在提供原文件下载..请大家有意见的提意见.....
文件说明
CORE.CSS请存放到12\_LAYOUTS\TEMPLATE\2052\STYLES\目录下
DEFAULT.MASTER请根据自己需要自行更改到母版页中
080711目录请存放到12\LAYOUTS\IMAGES目录下.
有问题请及时联系我,.....QQ10356075....lickies_1983@hotmail.com,,,建议论坛留言 ...
附件: default.rar (2008-10-23 21:48:33, 504.17 K)
那么可能很多人已经很讨厌了LOGIN.ASPX那个讨厌的页面了.
那么我们这个文章教大家如何制作精彩的LOGIN页面.首先我们来看我们的效果图
下面.把我做的LOGIN页面公布出来,并附图片,大家可以研究一下.
有兴趣的可以下载
那么,对于像我这样的专注于系统而没有开发经验的人来说,是不是就没有办法了呢?答案当然是否定的!在Sharepoint designer中,有一项神奇的功能,可以将MOSS的库和列表转换成XSLT数据视图,借助于XSLT,我们可以灵活的控制内容展示的形式。
比如,我们想对这个列表的标题的字数加以限制,当字数<=12时,则显示全部的标题,如果字数>12,则截取前面的9个字,并在后面加上...
在SPD中找到我们插入页面的库或列表,右键,选择转换成XSLT试图。
对于列表,选择列表的标题,对应的XSL代码为:
<xsl:value-of disable-output-escaping="no" select="@Title" />
将代码替换为:
<xsl:if test="string-length(@Title)<=12"> 判断如果标题的字符串长度是否<=12
<xsl:value-of disable-output-escaping="no" select="@Title" /> 显示完整标题:select="@Title"
</xsl:if>
<xsl:if test="string-length(@Title)>12"> 判断如果标题的字符串长度是否>12
<xsl:value-of select="substring(string(@Title),1,9)" />... 显示标题的前9个字符,并在后面加上 ...
</xsl:if>
对于文档库,select的值不是标题,而是将文件名处理后的标题,代码如下:
<xsl:value-of select="ddwrt:UrlBaseName(string(@LinkFilename))" />
我们需要将对应的代码修改如下:
<xsl:if test="string-length(@LinkFilename)<=12">
<xsl:value-of select="ddwrt:UrlBaseName(string(@LinkFilename))" />
</xsl:if>
<xsl:if test="string-length(@LinkFilename)>12">
<xsl:value-of select="substring(ddwrt:UrlBaseName(string(@LinkFilename)),1,9)" />...
</xsl:if>
美中不足的是,我发现代码中对于字符串的计数是不分全角半角的,统统按照一个计算,这样的话,如果标题或文件名中如果包含了半角的字母或数字,所显示的结果就不会如我们的想象一样,是一个固定的长度,不过,对于标题过长从而换行导致的布局问题,总算是解决了!
注:文中标题部分的代码,参考了西安huahua同学在MOSS群中的讨论,才使得我对这个问题有了一个完整的认识,在此表示感谢!
MOSS用那么久了,有人采用AD认证,有人采用FORM认证,我们公司是采用中间的替换方法,因为采用FORM认证个人觉得还是不是太方便,例如需要开两个端口等。个人有个做法把经验共享给大家,如果做得不对或者有更好的办法的话,可以联系我。
1.原因
为什么要进行表单登录,默认MOSS采用AD认证,是因为用户默认存储为AD,如果有人要把用户和以前的系统进行结合的方式,那么请采用正规的FORM认证进行开发。
我今天要讲的是AD认证,AD认证有个不好的方式就是弹出对话框,界面不友好,例如我要在界面上放一个忘记密码的方式是完全做不到的。
</P>
现在教大家一种采用表单进行提交的简单方法。其实这个办法很早的时候十一就搞过,不复杂,我只是稍微完善了一下。
1.首先采用匿名访问。
1.1IIS开启匿名访问。
</P>
1.2验证提供程序需要开启。操作方式:管理中心--》应用程序管理--》应用程序安全性--》验证提供程序--》默认
</P>
1.3开启网站匿名访问。操作为:网站操作--》高级权限--》设置--》匿名访问,如下
<BR></P>
2.设置登录界面
我们需要开发一个登录界面。输入用户。密码。
</
这个登录界面可以放在_LAYOUTS/目录底下。
登录界面代码请见附件。
需要改几个地址如下:
http://www.cnblogs.com/sharepoint/test/default.aspx 这个界面是需要验证的界面(默认网站已经开了匿名,只需要验证到其他一个非匿名访问的地址即可)
http://10.49.28.7 这个是我们要返回的界面
如果还不清楚的。可以访问http://keji.lickies.cn 查看。
3.登录后自动跳转到登录界面的方式,因为我们已经开放了匿名,默认我们是可以进去的,那么我们需要增加一段程序,判断如果AD用户为空的话则跳转到登录界面。
我们采用一个办法是在MASTERPAGE里增加一个USERCONTROL
如何做呢?打开默认的在12/TEMPLATE/GLOBRAL/DEFAULT.MASTER(如果有改过则到SPD里找)
在
<%@ Register TagPrefix="wssuc" TagName="Welcome" src="~/_controltemplates/Welcome.ascx" %>
下增加
<%@ Register TagPrefix="wssuc" TagName="login" Src="~/_controltemplates/chklogin9.ascx" %>
在<BODY scroll="yes" onload="javascript:if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();">
下增加
<wssuc:login id="chklogin" runat="server" EnableViewState="false"></wssuc:login>
可能很多人在问CHKLOGIN.ascx是啥。
就是我们的用户控件,,,这个文件如下。附件可以下载。。
<%@ Control Language="C#" Inherits="Microsoft.SharePoint.ApplicationPages.WebControls.ActionBar,Microsoft.
SharePoint,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" compilationMode="Always" %>
<%@ Register Tagprefix="wssawc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%
if(HttpContext.Current.User.Identity.Name.ToString()=="")
{
Response.Redirect("/_layouts/web/login.aspx");
}
%>
请把这个文件放到c:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES下即可。
大概写了一下。有问题的话,大家QQ群联系。
using System.DirectoryServices;
--先应用
--添加用户
DirectoryEntry entry = new DirectoryEntry(BaseFunctions.DomainSrv,HttpContext.Current.Session["username"].ToString(),HttpContext.Current.Session["password"].ToString(), AuthenticationTypes.Secure);
DirectoryEntry subEntry = entry.Children.Find(ou.Value);
DirectoryEntry deUser = subEntry.Children.Add("cn=" +firstname.Text.ToString()+lastname.Text.ToString(), "user");
deUser.Properties["userPrincipalName"].Add((accountname.Text.ToString()+"@"+BaseFunctions.Domainname));
deUser.Properties["samAccountName"].Add(accountname.Text.ToString());//帐户
deUser.Properties["description"].Value = desc.Text.ToString();
deUser.Properties["sn"].Add(firstname.Text.ToString());
deUser.Properties["givenName"].Add(lastname.Text.ToString());
deUser.Properties["displayName"].Add(firstname.Text.ToString()+lastname.Text.ToString());
deUser.CommitChanges();
deUser.Invoke("ChangePassword",new object[]{"",password.Text.ToString()});
deUser.Properties["userAccountControl"].Value = 0x200;
deUser.CommitChanges();
deUser.Close();
lblShowInfo.Text="添加成功";
----修改密码
if(tb_newpass.Value.Trim()!=tb_newpass1.Value.Trim())
{
lblShowInfo.Text="两次输入的新密码不一样";
return;
}
try
{
DirectoryEntry de=new DirectoryEntry(BaseFunctions.DomainSrv,BaseFunctions.GetUserNameFromSession(),BaseFunctions.GetPassWord());
DirectorySearcher deSearch = new DirectorySearcher(de);
deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(sAMAccountName="+Request.QueryString["username"]+"))";
deSearch.SearchScope = SearchScope.Subtree;
SearchResult result = deSearch.FindOne();
DirectoryEntry de1=result.GetDirectoryEntry();
object retResult=de1.Invoke("SetPassword", new Object[]{tb_newpass.Value.Trim()});
lblShowInfo.Text="成功修改密码!";
de1.Close();
de.Close();
de1.Dispose();
de.Dispose();
}
catch(Exception ex)
{
if(ex.InnerException!=null)
lblShowInfo.Text=ex.InnerException.Message;
else
lblShowInfo.Text+=ex.Message;
}
---将用户改变组织单位
DirectoryEntry de=new DirectoryEntry(BaseFunctions.DomainSrv,HttpContext.Current.Session["username"].ToString(),HttpContext.Current.Session["password"].ToString());
object o = de.NativeObject;
DirectorySearcher ds = new DirectorySearcher(de);
ds.Filter = "(SAMAccountName=" + Server.UrlDecode(Request.QueryString["username"]) + ")";
ds.PropertiesToLoad.Add("cn");
SearchResult sr = ds.FindOne();//查找该用户
//Response.Write(sr.GetDirectoryEntry().Properties["name"][0]);
DirectoryEntry de2=sr.GetDirectoryEntry();//设置de2为用户
DirectoryEntry ou2 = de.Children.Find(Request.QueryString["ou"]);//获取新ou对象
de2.MoveTo(ou2);//移动OU
de2.CommitChanges();//提交
Response.Write("<script language=javascript>");
Response.Write("alert('移动完毕');");
Response.Write("opener.window.location.reload(true);");
Response.Write("window.close();");
Response.Write("</script>");
--用递归方式显示组织单位.还有小部分没做好,只是显示出来,没优化,有兴趣的同志可以改界面呈现方式
调用函数
GetOu("泉州移动",5);----5代表是显示5级
public void GetOu(string ouname,int amstr)
{
DirectoryEntry entry=new DirectoryEntry(BaseFunctions.DomainSrv,BaseFunctions.GetUserNameFromSession(),BaseFunctions.GetPassWord());
System.DirectoryServices.DirectoryEntry subentry=entry.Children.Find(ouname,"organizationalUnit");
string ax;
ax="";
string am;
am="";
foreach(DirectoryEntry res in subentry.Children)
{
am="";
foreach(DirectoryEntry res1 in res.Children)
{
if(res1.Name.Substring(0,3)=="OU=")
{
am=am+"1";
}
}
if(res.Name.Substring(0,3)=="OU=")//判断是组织单位还是其他类型,例如cn=用户,GROUP=组等
{
ax=ax+"1";
string []strArray;//用于存储上级目录的字符串
string ou;
ou="";
strArray=ouname.Split(',');//分割
for(int j=strArray.Length;j>0;j--)
{
if(j==1)
{
if(amstr==ax.Length)
{
HttpContext.Current.Response.Write("<img src=images/tree2.gif>");
}
else
{
HttpContext.Current.Response.Write("<img src=images/tree1.gif>");
}
}
else
{
HttpContext.Current.Response.Write("<img src=images/tree3.gif>");
}
}//根据上级目录的深度来显示目录树的层次
if(am=="")
{
Response.Write("<img src=images/tree6.gif>");
}
else
{
Response.Write("<img src=images/tree5.gif>");
}
string []strArray2;
string tem;
tem=res.Name.ToString()+","+ouname;//存储本级目录
strArray2=tem.Split(',');
for(int k=strArray2.Length;k>0;k--)
{
ou=ou+strArray2[k-1].Replace("OU=","/");
}
//OU存储本级目录的新格式,例如.泉州移动--网络部--IT中心等
if(HttpContext.Current.Request.QueryString["action"]=="move")
{
HttpContext.Current.Response.Write("<a onclick=movechk('"+Server.UrlEncode(res.Name.ToString()+","+ouname)+"','"+HttpContext.Current.Request.QueryString["username"]+"');>"+res.Name.ToString().Replace("OU=","")+"</a><br>");
}
else if(HttpContext.Current.Request.QueryString["action"]=="add")
{
HttpContext.Current.Response.Write("<a onclick=chk('"+ou+"','"+res.Name.ToString()+","+ouname+"');>"+res.Name.ToString().Replace("OU=","")+"</a><br>");
}
else
{
HttpContext.Current.Response.Write("<a onclick=magchk('"+Server.UrlEncode(res.Name.ToString()+","+ouname)+"');>"+res.Name.ToString().Replace("OU=","")+"</a><br>");
}
GetOu(res.Name.ToString()+","+ouname,am.Length);
}
else
{
}
}
----显示所有域用户的信息
DirectoryEntry de = new DirectoryEntry(BaseFunctions.DomainSrv,HttpContext.Current.Session["username"].ToString(),HttpContext.Current.Session["password"].ToString());
DirectorySearcher srch=new DirectorySearcher();
srch.Filter =("(objectclass=User)");
srch.SearchRoot=de;
srch.SearchScope = SearchScope.Subtree;
srch.PropertiesToLoad.Add("sn");
srch.PropertiesToLoad.Add("givenName");
srch.PropertiesToLoad.Add("uid");
srch.PropertiesToLoad.Add("telephoneNumber");
srch.PropertiesToLoad.Add("employeeNumber");
Response.Write("<table width=100% border=0 align=center Class=border");
Response.Write("<tr background=images/topbar_bg.gif>");
Response.Write("<td align=center height=22>帐号</td>");
Response.Write("<td align=center height=22>名字</td>");
Response.Write("<td align=center height=22>姓</td>");
Response.Write("<td align=center height=22>名</td>");
Response.Write("<td align=center height=22>显示名称</td>");
Response.Write("<td align=center height=22>手机</td>");
Response.Write("<td align=center height=22>部门</td>");
Response.Write("<td align=center height=22>状态</td>");
Response.Write("</tr>");
foreach(SearchResult res in srch.FindAll())
{
if(res.Path.IndexOf("泉州移动")>0)
{
Response.Write("<tr class=tdbg>");
Response.Write("<td align=center>"+res.GetDirectoryEntry().Properties["sAMAccountName"][0]+"</td>");
Response.Write("<td align=center>"+res.GetDirectoryEntry().Properties["Name"][0]+"</td>");
Response.Write("<td align=center>"+res.GetDirectoryEntry().Properties["Sn"][0]+"</td>");
try
{
Response.Write("<td align=center>"+res.GetDirectoryEntry().Properties["givenName"][0]+"</td>");
}
catch
{
Response.Write("<td align=center></td>");
}
Response.Write("<td align=center>"+res.GetDirectoryEntry().Properties["displayName"][0]+"</td>");
try
{
Response.Write("<td align=center>"+res.GetDirectoryEntry().Properties["telephoneNumber"][0]+"</td>");
}
catch
{
Response.Write("<td align=center></td>");
}
try
{
Response.Write("<td align=center>"+res.GetDirectoryEntry().Properties["mail"][0]+"</td>");
}
catch
{
Response.Write("<td align=center></td>");
}
string []strArray;
string str;
str="";
strArray=res.Path.Split(',');
for(int j=strArray.Length;j>0;j--)
{
if(strArray[j-1].Substring(0,3)=="OU=")
{
str=str+"-"+strArray[j-1].Replace("OU=","");
}
}
Response.Write("<td align=center>"+str+"</td>");
if(res.GetDirectoryEntry().Properties["userAccountControl"][0].ToString()=="514")
{
Response.Write("<td align=center>锁定</td>");
}
else
{
Response.Write("<td align=center>正常</td>");
}
/*
Response.Write("<td align=center>");
if(res.GetDirectoryEntry().Properties["userAccountControl"][0].ToString()=="514")
{
Response.Write("<input type=button value=解锁 onclick=\"javascript:window.open('setstate.aspx?action=1&username="+res.GetDirectoryEntry().Properties["sAMAccountName"][0]+"', 'poppage', 'toolbars=1, scrollbars=0, location=0, statusbars=1, menubars=0, resizable=1, width=50, height=50');\">");
}
else
{
Response.Write("<input type=button value=锁定 onclick=\"javascript:window.open('setstate.aspx?action=2&username="+res.GetDirectoryEntry().Properties["sAMAccountName"][0]+"', 'poppage', 'toolbars=1, scrollbars=0, location=0, statusbars=1, menubars=0, resizable=1, width=50, height=50');\">");
}
Response.Write("<input type=button value=移动部门 onclick=\"javascript:window.open('ou.aspx?action=move&username="+res.GetDirectoryEntry().Properties["sAMAccountName"][0]+"', 'poppage', 'toolbars=1, scrollbars=1, location=0, statusbars=1, menubars=0, resizable=1, width=200, height=650');\">");
Response.Write("<input type=button value=更改密码 onclick=\"javascript:window.open('changeuserpass.aspx?action=password&username="+res.GetDirectoryEntry().Properties["sAMAccountName"][0]+"', 'poppage', 'toolbars=1, scrollbars=1, location=0, statusbars=1, menubars=0, resizable=1, width=500, height=150');\">");
Response.Write("</td>");
*/
Response.Write("</tr>");
//CreateExcelFile2(res.GetDirectoryEntry().Password.ToString(),res.GetDirectoryEntry().Properties["Name"][0].ToString(),res.GetDirectoryEntry().Properties["telephoneNumber"][0].ToString(),res.GetDirectoryEntry().Properties["sn"][0].ToString(),res.GetDirectoryEntry().Properties["givenName"][0].ToString(),res.GetDirectoryEntry().Properties["displayName"][0].ToString());
}
}
Response.Write("</table>");
一个sharepoint网站的主题基础的包含theme.inf,theme.css和一些images文件,theme.inf文件简单的描述主题的标题等信息,theme.css是一个样式文件,他描述了诸如颜色、banner页眉、images图片以及其他一些显示在界面上的样式。当你有上百个对象需要去处理的话,你可以通过定义网站主题来改变轻易的这些样式。
接下来,我们来做一个简单的样例,创建一个网站主题,名称叫做"GHOST".
1.进入 "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\THEMES"文件夹,则可以看到一些目录,这些其实就是网站主题那些样式的目录以及themes.inf来描述网站的主题的相关信息。现在,我们复制其中一个主题GRANITE,并且重新命名为GHOST
2进入GHOST文件夹,更换文件名GRANITE.INF为GHOST.INF
3.打开GHOST.INF
4.修改标题的信息为GHOST
5.将TITLE中的GRANITE批量替换为GHOST
6.打开C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\2052\SPTHEMES.XML
7在下方增加一下代码
Ghost
Ghost
Ghost theme.
images/thghost.gif
images/thghost.gif
注意:预览的图片地址为thghost.gif默认MOSS没有这个图片,需要自己上传。
8.为了显示预览正确,你将需要截取屏幕并且保存文件到
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\IMAGES目录,并且命名为thghost.gif,你可以修改这个GIF文件名,如果你在TEMPLATES里修改了预览文件名的话。
9.最后IISreset一下,再配置到新的主题里,就可以查看到新的主题了。
10.你可以更改这些新的主题,例如IMAGES,THEME.CSS来控制很多的属性。
如何利用Sharepoint开发一个完全不同与Sharepoint风格的站点其实和普通的.NET站点是完全不一样的,首先必须熟悉MOSS的很多功能,例如WEBPART,EVENTHANDLER,内容类型,CUSTOMER FIELD等,其实提供的是一个整体的解决方案,根据不同的需求来规划设计出不同的方案,因此经验和规划能力更重要。
步骤一:定义基本的网站地图和设计
就像许多Web项目一样,基本的站点地图和设计告诉开发团队基本的功能需求。站点地图能够使我们知道在站点上的各种不同类型的页面,设计使我们知道需要使用什么样的Feature.两者会随着进程不断的变化,但是他们给我们提供了项目开始的基线。
步骤二:定义自己的Content Columns 和Content Types
Content Types 是SharePoint的巨大特色,它为整个站点提供了底层结构。在项目的初期花费时间定义页面布局和Lists所需要的Content types是值得的。不需要定义的特别彻底,但是在开始时在这方面做的工作越多,以后返工的工作就少。
可以在项目中创建若干个Content Type组。例如”HedKandi Page Layout Content Types”和”HedKandi Custom List Content Types”.这主要考虑到当最终用户创建views时有更好的用户体验,同时也可以容易区分哪一个是开箱即用的content types,哪一个是我们创建的。
步骤3:定义自定义Lists
Lists是项目的骨架,可以创建若干个Site Collection级别的Lists以保证一致性和内容的复用。
步骤4:创建基本的站点层次结构
如果站点的层次结构不复杂,那就在Site Action用户界面下创建层次结构。如果是一个相当大的站点,那就应该提前创建整个站点的层次结构,建议使用 Stsadm –o createsite 命令或写一个简单的应用程序通过API自动创建层次结构。
步骤5 加入图像和CSS文件
一旦拥有了基本的站点架构,Custom content types和Lists,就可以开始把站点建造成设计的样子。这是我们第一次使用SharePoint Designer的时候,利用SPD可以非常容易地加入Css文件。至于Content Types如果想确保我们知道哪一些是开箱即用的,哪一些是我们在工程期间加入的,可以在Style Library List中加入新的目录例如叫做HedKandi,在这个目录下分别创建CSS和Images目录,我们把图像和CSS文件分别放到这些目录中。
步骤6 建立自己的Master Pages
因为工程中有许多布局大不相同页面,而且它们位于站点的不同位置,所以选择使用多个Master Pages。由于已经对XHMTL文件做了大量的工作,所以我们可以快速的创建新的Master Pages.因为我们想要利用站点中现有页面布局,所以我们对 控件保持同样的命名规则。
步骤7 创建自己的页面布局
这时我们可以真正看到预定义好的Page Layout Content Types以及XHTML的益处。当做了这些工作后创建一个平面的页面布局是相当快速的,主要是由于SPD的工具箱和SharePoint的高度集成。把content field加入到页面中,只要把它从工具箱中选中,拖拽到页面上就行了,不论是在设计模式还是代码模式下。如果已经很好定义了Content Type并且进行了适当的描述,这样开发人员就不必总是通过参考文档才知道field control是做什么的,这些controls应该是什么格式的,这将在工程中大大节省时间。
这时,我们就拥有了一个可以工作的站点,看起来非常接近设计的样子,可以让作者开始向Lists输入内容,创建基于Page Layouts的页面。这就勾勒出了测试过程,因为这意味着我们能够捕捉到丢失的Fields或功能。
步骤8 定制自己的Content Query webpart 视图
Content Query wb part是在网站中最常用的webpart之一。我们在各处使用它们从Lists中集合内容数据。我们发现为了满足设计上的需要,可以快速的变化web part提供的一套标准的视图。我们可以创建定制的XSLT模版以满足需求,通过修改itemstyle.xsl文件――位于站点集合根目录下的/Style Library/XSL Style Sheets
通过给itemstyle.xsl文件增加一个新的XSLT模版就自动的把其中的内容增加到Web part属性的下拉列表中。这非常省时,但是要注意文件中语法错误会导致在Site Collection中的所有的Content Query webparts实例崩溃。
MOSS项目需要注意的几大问题
1.客户满意
带给客户期望的好处和业务,需要和客户详细沟通,不允许直接从功能需求上考虑实现,设置正确的客户期望值
2.稳定
网站开发完后希望有稳定的运行,更多的是服务器设置的一些问题,性能等,
3.安全
这个也是MOSS比较头疼的问题,MOSS本身已经有很强大的权限管理,但是也需要一定的管理,例如网站的权限,列表的权限,记录的自定义权限等,权限是否需要继承等诸多问题,访问群体,这些权限的设置应该如何设置,是需要很多经验积累的,例如有很多人通过视图不显示这些数据,但是事实上,这些数据是可以通过URL地址等各类方式来显示的。必须从根本上来限制他的安全级别。
4.扩展
为明天去做设计,让用户长期使用,很有感悟,曾经看到群里一个网友发布他的MOSS站点的设计,事实上他做的不错,MOSS已经被他改的面目全非了。界面也很漂亮,但是我们会发现,他所有的WEBPART都是写死得。想随便拖拉一下都不可以,那这样还不如写个.NET程序。用MOSS就是希望尽量的挖掘他的功能,减少开发量和维护量,而这个东西扩展的性能就非常重要。
5.灵活
MOSS有feature,customer field,masterpage,这些.NET2.0的特性,便于日后的升级是非常有好处的。因为至少.NET3.5的内核和.ET3.0没有太大的核心的变化。
如果有问题的话可以在留言板里提问,然后留下你的EMAIL方式,我会将解答发送到你的EMAIL。
1.在图片库的FEATURE里,修改XML描述文件
在12目录下找到FEATURE目录,找到picture的FEATURE修改相应的目录,因为你修改了。则所有的图片都会生效。这个是一个好的解决方案,不是太建议这个办法,因为有些时候你可能要针对不同的图片库设置不同的大小。
2。使用对象模型写代码修改预览图片的大小。
模型代码为,图片库对象的ThumbnailSize属性。
这个方法也可行,但是这取决于你知道如何为sharepoint写代码。不会写代码的人就不能用这个方法啦。
3.使用sharepoint manager2007软件修改预览图片大小,。现在介绍第三种方式,也是比较方便的一个方式。
1)首先下载sharepoint manager 2007
http://www.keutmann.dk/sharepointblog/spm2007.zip
2)在服务器上打开执行程序。
3)找到图片库的位置并选择THUMBNAILSITE属性,如下图
Find the picture library you want to change and select the ThumbnailSize property
为该属性设置大小。
保存设置并且刷新界面,则你可以看到下图的效果。
good。完成
当我们新增加一个字段为用户类型,例如用户组等。是一个多选的。
那么我们如何通过代码的方式给这个类型增加用户呢。
可以用以下的方式
using (SPSite site = new SPSite("http://site"))
{
using (SPWeb web = site.AllWebs["Web"])
{
SPList list = web.Lists["List"];
SPListItem item = list.Items[0];
SPFieldUserValueCollection values = (SPFieldUserValueCollection)item["Users"];
SPUserCollection users = web.AllUsers;
foreach (SPUser user in users)
{
values.Add(new SPFieldUserValue(web, user.ID, user.Name));
}
item["Users"] = values;
item.Update();
}
}
大家看明白了吗?
网上一有一篇文章,来很仔细的描述如何增加自定义字段的.可能大家都有见过。这里就不在详细讲如何创建自定义字段了。
有兴趣的话可以查看我BLOG的另外一篇文章http://blog.lickies.cn/Lists/Posts/ViewPost.aspx?ID=17
----------------------------------------
接下来,我来告诉大家如何做TREEVIEW的树型菜单.
首先修改.ASCX文件
<% @ Control Language="C#" Debug="true"%>
<% @ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<% @ Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=12.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" Namespace="Microsoft.SharePoint.WebControls" %>
<SharePoint:RenderingTemplate ID="SelectItemFromXMLFieldControl" runat="server">
<Template>
<asp:TextBox ID="txt_Ou" runat="server"></asp:TextBox>
<asp:TreeView ID="TreeView1" runat="server" ShowLines="True">
</asp:TreeView>
</Template>
</SharePoint:RenderingTemplate>
修改SelectItemFromXML.FieldControl.cs文件
using System;
using System.Runtime.InteropServices;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.UI.WebControls;
using System.IO;
using System.Xml;
using System.Diagnostics;
using System.DirectoryServices;
namespace SelectItemFromXML
{
[CLSCompliant(false)]
[Guid("eb269bd9-0d3e-4aa2-b88f-37fbccb0d7d8")]
public class SelectItemFromXMLFieldControl : BaseFieldControl
{
protected TreeView TreeView1;
protected TextBox txt_Ou;
protected override string DefaultTemplateName
{
get
{
return "SelectItemFromXMLFieldControl";
}
}
public override object Value
{
get
{
EnsureChildControls();
return txt_Ou.Text;
}
set
{
EnsureChildControls();
txt_Ou.Text = (string)this.ItemFieldValue;
}
}
public override void Focus()
{
EnsureChildControls();
txt_Ou.Focus();
}
protected override void CreateChildControls()
{
if (Field == null) return;
base.CreateChildControls();
if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.Display)
return;
txt_Ou = (TextBox)TemplateContainer.FindControl("txt_Ou");
TreeView1 = (TreeView)TemplateContainer.FindControl("TreeView1");
if (!Page.IsPostBack)
{
TreeNode node2 = new TreeNode();
node2.Text = "泉州移动";
TreeView1.Nodes.Add(node2);
GetOu("OU=泉州移动", 10,node2);
}
}
protected void TreeView1_SelectNodeChanged(object sender, EventArgs e)
{
}
public void GetOu(string ouname, int amstr,TreeNode nodetmp)
{
//获取AD的对象
//搜索组织单位
DirectoryEntry entry = new DirectoryEntry("LDAP://SHAREPOINT2007.QZIT.COM", "administrator", "你的密码");
//获取子结点
System.DirectoryServices.DirectoryEntry subentry = entry.Children.Find(ouname, "organizationalUnit");
//对子对象进行循环
foreach (DirectoryEntry res in subentry.Children)
{
if (res.Name.Substring(0, 3) == "OU=")//判断是否为OU
{
//增加子结点
TreeNode node2 = new TreeNode();
node2.Text = res.Name.ToString().Replace("OU=", "") ;
nodetmp.ChildNodes.Add(node2);
//递归调用
GetOu(res.Name.ToString()+","+ouname, 10,node2);
}
}
}
}
}
其中必须确定在AD根结点下建立一个泉州移动的组织单位(也可修改其中代码)
那么,首先我们来看moss默认的用户选择器
这个界面很适合老外的简单操作的风格,但是对于有中国特色的组织那就没有办法了。
那么,我们通过开发一个自定义字段来解决这样的一些问题。
首先我们把编写好的自定义字段安装上去,该步骤省略,等我的整体解决方案公布后会提供安装的方法,现在由于只是DEMO,就没有直接放代码了。
我们可以看到下图

已经有了用来调用组织单位的目录树的自定义字段了。
设置标题为选择人员,点击确定得到下图

从这个图中我们可以看出这个自定义字段有两个控件,一个是文本框,用来存储你选择的用户,另外一个是连接,由于用户选择器一般都比较大,我选择新弹出窗口来实现,而不直接写到自定义字段内,新弹出的窗口是一个标准的ASPX的文件,我们可以把它部署在_LAYOUTS目录地下。
下面我们点击选择,就会跳出下面的窗口

从这张图中你就可以看出大概的样子了。
左边这个是用TREEVIEW递归读取的AD的组织结构
当我们点击某个部门的时候,他将列举出该部门下的所有人员,如下图
细心的同学可以发现在中间的框里有一个包含下级的选择框,当我们打勾后将出现该部门的下属部门的所有人员,方便管理人员选择他的直接下级。
在人员列出后,我们打勾进行人员选择,点旁边的>>号即可将这些人员提交到第三栏,当前选择人员中。如下图


最后我们将该记录保存,在查看视图中可以发现,我们的记录事实上是以登录的帐号来进行保存的,以确定唯一性,如下图

好了。演示完毕,
目前只是demo,接下来还要做的是整理成WSP包,以及存储成user字段,参数设置等调整,请大家耐心等待。如果有什么问题,请到我的BLOG进行留言。








我们在列表中还有很多不能解决的问题,下面我们介绍一下用栏的计算值的方式来解决这一问题
例如:
我们要填写一个周报.根据每周的周五要汇总提交.我们要如何实现呢
首先.新建立一个计算栏
叫周报填写日期
值为:=发表时间-WEEKDAY(发表时间,2)+IF(WEEKDAY(发表时间,2)>=6,12,5)
解释一下:例如发表是周三,3月12日,减去WEEKDAY(发表时间,2)即为每周的头一天,即周日,再加5,就是我们要的每周周五汇报
这样就有一个列表,是按周报填写日期分组的一批数据了
例如
2月26日
3月4日
3月12日
那我们如何汇总本周周报呢.其实很简单了
我们新建立一个视图...筛选条件为周报填写日期大于等于[今日]
是否很简单呢?试试就知道
之后的样式

如何做呢??
找到CSS 的默认样式的地方
在 Local Drive:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\2052\STYLES\CORE.CSS
找到2666行
默认为
.ms-WPHeader TD{
color: #345456;
border-bottom:1px solid #4e7cb7;
border-collapse:collapse;
}
修改为
.ms-WPHeader TD{
color: #345456;
height:24px;
border-bottom:1px solid #4e7cb7;
border-collapse:collapse;
background-image:url('/_layouts/images/title.gif');
}
然后在下面增加
.ms-WPHeader span{
font:9pt 宋体;
font-weight:bold;
color:#ffffff;
text-decoration:none;
}
用来设置WEBPART上的标题连接的颜色.
这样就OK了喔...




