Andrew Robinson, the president of the Bellingham .NET Users Group, invited me to give a talk to his group. I will be giving them a talk on "WebParts for SharePoint 2007" on Wednesday January 8, 2007 starting at 6:00 PM. Bellingham is the most visited city accross the border for British Columbians and I look forward to forging closer ties between .netBC and the Bellingham .NET Users Groups.
Here is the extract of my talk:
WebParts for SharePoint 2007
WebParts provide the fundamental building blocks for creating custom applications for SharePoint. This session will show you how to efficiently and quickly use your ASP.NET 2.0 and C# skills to develop WebParts for deployment into SharePoint 2007. Most of the development, testing and debugging will be done in Visual Studio .NET 2007. We shall then deploy the WebPart as a feature into Windows SharePoint Services 3.0 (WSS 3.0). We will also look at WebPart communication and modifying WebPart verb menus.
Wednesday January 9, 2008
The files that make up my presentation can be downloaded from here.
Thursday January 10, 2008
I had an enjoyable time at Bellingham. There were 13 people in attendance. Pizza was great and I was glad that they serve water instead of the dreaded pop.
Friday, December 28, 2007
Wednesday, December 19, 2007
Move SharePoint 2007 paging control from the right to the left of the action bar.
A user at my workplace has a view that is horizontally very wide. It drives him nuts to have to scroll all the way to the extreme right of the page in order to find the paging control. He pleaded with me to find a way to move this control to the left side of the action bar. After many hours of research, here's what I found:
The default layout of the action bar is defined in a user control file named DefaultTemplates.ascx found in the TEMPLATE\CONTROL TEMPLATES directory of your 12-hives
The default layout can be alterted for a particular type of list be over-riding the "ViewToolBar" for that list.
This is best done by working on a copy of DefaultTemplates.ascx
I moved the paging control for the DocumentLibraryViewToolBar to the left-hand-side by doing the following:
copy DefaultTemplates.ascx to PagingLeftOnDocLibrary.ascx (or any other name you fancy).
open PagingLeftOnDocLibrary.ascx in a text editor
search for DocumentLibraryViewToolBar. Your editor should find this line: <SharePoint:RenderingTemplate ID="DocumentLibraryViewToolBar" runat="server">
delete all <SharePoint:RenderingTemplate>.. </SharePoint:RenderingTemplate> sections before and after the section that you have just found. In other words retain the section <SharePoint:RenderingTemplate ID="DocumentLibraryViewToolBar" runat="server"> .. </SharePoint:RenderingTemplate> and delete all other sections
You will be left with only the following:
<%@ Control Language="C#" AutoEventWireup="false" %>
<%@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"%>
<%@Register TagPrefix="SPHttpUtility" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Utilities"%>
<%@ Register TagPrefix="wssuc" TagName="ToolBar" src="~/_controltemplates/ToolBar.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ToolBarButton" src="~/_controltemplates/ToolBarButton.ascx" %>
<SharePoint:RenderingTemplate ID="DocumentLibraryViewToolBar" runat="server">
<Template>
<wssuc:ToolBar
CssClass="ms-menutoolbar"
EnableViewState="false"
id="toolBarTbl"
ButtonSeparator="<img src='/_layouts/images/blank.gif'
alt=''>" RightButtonSeparator=" "
runat="server">
<Template_Buttons>
<SharePoint:NewMenu AccessKey="<%$Resources:wss,tb_NewMenu_AK%>" runat="server"/>
<SharePoint:UploadMenu AccessKey="<%$Resources:wss,tb_UploadMenu_AK%>" runat="server"/>
<SharePoint:ActionsMenu AccessKey="<%$Resources:wss,tb_ActionsMenu_AK%>" runat="server"/>
<SharePoint:SettingsMenu AccessKey="<%$Resources:wss,tb_SettingsMenu_AK%>" runat="server"/>
</Template_Buttons>
<Template_RightButtons>
<SharePoint:PagingButton runat="server"/>
<SharePoint:ListViewSelector runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
</Template>
</SharePoint:RenderingTemplate>
The PagingButton section (shown in red above) needs to be moved to the Template_Buttons section. I simply cut <SharePoint:PagingButton runat="server"/> and pasted it right before </Template_Buttons>
If you restart IIS (IISRESET from the command line) you should see the paging control on the left-hand-side of the document library action bar as shown below.
The final version of my PagingLeftOnDocLibrary.ascx is:
<%@ Control Language="C#" AutoEventWireup="false" %>
<%@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"%>
<%@Register TagPrefix="SPHttpUtility" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Utilities"%>
<%@ Register TagPrefix="wssuc" TagName="ToolBar" src="~/_controltemplates/ToolBar.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ToolBarButton" src="~/_controltemplates/ToolBarButton.ascx" %>
<SharePoint:RenderingTemplate ID="DocumentLibraryViewToolBar" runat="server">
<Template>
<wssuc:ToolBar
CssClass="ms-menutoolbar"
EnableViewState="false"
id="toolBarTbl"
ButtonSeparator="<img src='/_layouts/images/blank.gif'
alt=''>" RightButtonSeparator=" "
runat="server">
<Template_Buttons>
<SharePoint:NewMenu AccessKey="<%$Resources:wss,tb_NewMenu_AK%>" runat="server"/>
<SharePoint:UploadMenu AccessKey="<%$Resources:wss,tb_UploadMenu_AK%>" runat="server"/>
<SharePoint:ActionsMenu AccessKey="<%$Resources:wss,tb_ActionsMenu_AK%>" runat="server"/>
<SharePoint:SettingsMenu AccessKey="<%$Resources:wss,tb_SettingsMenu_AK%>" runat="server"/>
<SharePoint:PagingButton runat="server"/>
</Template_Buttons>
<Template_RightButtons>
<SharePoint:ListViewSelector runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
</Template>
</SharePoint:RenderingTemplate>
Friday, November 30, 2007
DevTeach & SqlTeach conference held in Vancouver from 26nov07 to 30nov07
The highlight for me was the open ended bar night named "Party with Palermo" held on Monday night (26nov07) at the Steamworks brewery. It was a blast and happiness was being propelled by the alcohol level flowing through our veins. Unfortunately, I left early around 9:45 PM because I had to teach at BCIT very early the next morning. I know of a few who were there until midnight. Thanks Jeffrey Palermo.
The other highlight was the Mad Mexican's second appearance at DevTeach. He barged into Beth Massi's presentation to emphasize how great she is. Check out this blog entry.
I spoke on Wednesday 28nov07 on the topic of "SharePoint 2007 Advanced Development". Attendance was about 40 people. All went well except for the last part involving installation of the SharePoint workflow. After the simple workflow was deployed and activated it did not work. I did not bother trouble-shooting the problem because I was already about 15 minutes overtime. However, I later discovered that I had failed to set one of the dreaded GUIDs in the Manifest.XML. Oh well, as the saying goes "Shit Happens".
All in all it was a lot of fun and I am very happy for Jean-Rene that his first-time conference in Vancouver was indeed a success.
The other highlight was the Mad Mexican's second appearance at DevTeach. He barged into Beth Massi's presentation to emphasize how great she is. Check out this blog entry.
I spoke on Wednesday 28nov07 on the topic of "SharePoint 2007 Advanced Development". Attendance was about 40 people. All went well except for the last part involving installation of the SharePoint workflow. After the simple workflow was deployed and activated it did not work. I did not bother trouble-shooting the problem because I was already about 15 minutes overtime. However, I later discovered that I had failed to set one of the dreaded GUIDs in the Manifest.XML. Oh well, as the saying goes "Shit Happens".
All in all it was a lot of fun and I am very happy for Jean-Rene that his first-time conference in Vancouver was indeed a success.
Saturday, November 24, 2007
How do I enable more detailed error messages in SharePoint 2007 for debugging purposes?
The error messages generated by SharePoint 2007 are not very useful. If you are doing some serious development work in SharePoint you will need to temporarily enable error messages. This is done by making the following changes to your web.config file:
1) Change the "CallStack" attribute in the <SafeMode> element from "false" to "true".
<SafeMode MaxControls="200" CallStack="true"
DirectFileDependencies="10"
TotalFileDependencies="50"
AllowPageLevelTrace="false">
2) Change the "mode" attribute in the <customErrors> element from "On" to "Off".
<customErrors mode="Off" />
1) Change the "CallStack" attribute in the <SafeMode> element from "false" to "true".
<SafeMode MaxControls="200" CallStack="true"
DirectFileDependencies="10"
TotalFileDependencies="50"
AllowPageLevelTrace="false">
2) Change the "mode" attribute in the <customErrors> element from "On" to "Off".
<customErrors mode="Off" />
Tuesday, October 30, 2007
Simulate Parent / Child relationship in SharePoint 2007 with Folders & Content Types
One can create Parent / Child (A.K.A. Master / Detail) relationships in SharePoint 2007 by using lookups to reference a parent list from a child list. I will discuss another way of creating a Parent / Child relationship by adding a content type inside a folder.
We will create a parent / child relationship between company and employees. Here are our sample entities:
Company Parent (CompanyId, CompanyName)
Employee Child (Name, EmployeeId, Branch)
The strategy will be to make the "Company Parent" entity a folder which contains "Employee Child" items. To accomplish this we will create two new content types for each entity.
The "Company Parent" content type:
1) Site Actions ==> Site Settings ==> Site Content Types
2) Create
• Name: Company Parent
• Select parent content type from: Folder Content Types
• Parent Content Type: Folder
• Existing group: Custom Content Types
• Click OK
3) Click on "Add from new site column" on the "Site Content Type: …" page under column.
• Column name: CompanyId of type Number
• Click OK
NOTE: We will reuse the "Title" field to be the CompanyName.
The "Employee Child" content type:
1) Site Actions ==> Site Settings ==> Site Content Types
2) Create
• Name: Employee Child
• Select parent content type from: List Content Types
• Parent Content Type: Item
• Existing group: Custom Content Types
• Click OK
3) Click on "Add from new site column" on the "Site Content Type: …" page under column.
• Column name: EmployeeId of type Number
• Click OK
4) Click on "Add from new site column" on the "Site Content Type: …" page under column.
• Column name: Branch of type "Single line of text"
• Click OK
NOTE: We will reuse the "Title" field to be the EmployeeName.
Now we can go about our normal business of creating a custom list and using our two newly created content types "Company Parent" and "Employee Child".
1) Site Settings ==> Create
2) Click on "Custom List" under the "Custom Lists" column.
• Name: CompanyEmployees
• Click OK
3) Settings ==-> List Settings
4) Click on "Advanced Settings" under the "General Settings" column
5) At the very top, change Allow management of content types?" to Yes.
6) Click on OK
7) Under "Content Types" click on "Add from existing site content types".
8) On the "Add Content Types:" page
• Select site content types from: Custom Content Types
• Add "Company Parent" and "Employee Child" content types.
• Click on OK
Let’s add some dummy data.
1. Click on the "CompanyEmployees" list
2. Click on the little arrow beside New. You should see this:
3. Select "Company Parent"
4. Add the following bogus company data:
• Name: ACME Corporation; CompanyId: 123
• Name: Bogus Enterprises: CompanyId: 456
5. Add bogus company employees to "ACME Corporation"
• Click on "ACME Corporation". This causes the folder to open.
• Add the following employees to the ACME Corporation by clicking on New ==-> Employee Child:
• Title: Jane Doe; EmployeeId: 111; Branch: Downtown
• Title: James White; EmployeeId: 222; Branch: Airport
• Click on "Bogus Enterprises". This causes the folder to open.
• Add the following employees to Bogus Enterprises by clicking on New ==-> Employee Child:
• Title: Judy Black; EmployeeId: 333; Branch: Main Street
• Title: Brandon Wiley; EmployeeId: 333; Branch: Riverside
• Add another employee to ACME:
This concludes configuration and data entry. Let us now use the SharePoint 2007 Object Model to get at this data.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
public class CompanyEmployees {
static void Main(string[] args) {
SPSite site = new SPSite("http://srvr/");
SPWeb web = site.AllWebs["/"];
SPList list = web.Lists["CompanyEmployees"];
foreach (SPListItem order in list.Folders) {
Console.WriteLine("Company ID : {0}", order["CompanyId"]);
Console.WriteLine("Company Name : {0}", order["Title"]);
SPQuery empItemsQuery = new SPQuery();
empItemsQuery.Folder = order.Folder;
SPListItemCollection empItems = list.GetItems(empItemsQuery);
foreach (SPListItem empItem in empItems) {
Console.WriteLine("\tEmployee ID {0}: {1} {2}",
empItem["EmployeeId"],
empItem["Title"],
empItem["Branch"]);
}
}
}
}
The above application will produce the following result:
Company ID : 123
Company Name : ACME Corporation
Employee ID 111: Jane Doe Downtown
Employee ID 222: James White Airport
Company ID : 456
Company Name : Bogus Enterprises
Employee ID 333: Judy Black Main Street
Employee ID 444: Brandon Wiley Riverside
We will create a parent / child relationship between company and employees. Here are our sample entities:
Company Parent (CompanyId, CompanyName)
Employee Child (Name, EmployeeId, Branch)
The strategy will be to make the "Company Parent" entity a folder which contains "Employee Child" items. To accomplish this we will create two new content types for each entity.
The "Company Parent" content type:
1) Site Actions ==> Site Settings ==> Site Content Types
2) Create
• Name: Company Parent
• Select parent content type from: Folder Content Types
• Parent Content Type: Folder
• Existing group: Custom Content Types
• Click OK
3) Click on "Add from new site column" on the "Site Content Type: …" page under column.
• Column name: CompanyId of type Number
• Click OK
NOTE: We will reuse the "Title" field to be the CompanyName.
The "Employee Child" content type:
1) Site Actions ==> Site Settings ==> Site Content Types
2) Create
• Name: Employee Child
• Select parent content type from: List Content Types
• Parent Content Type: Item
• Existing group: Custom Content Types
• Click OK
3) Click on "Add from new site column" on the "Site Content Type: …" page under column.
• Column name: EmployeeId of type Number
• Click OK
4) Click on "Add from new site column" on the "Site Content Type: …" page under column.
• Column name: Branch of type "Single line of text"
• Click OK
NOTE: We will reuse the "Title" field to be the EmployeeName.
Now we can go about our normal business of creating a custom list and using our two newly created content types "Company Parent" and "Employee Child".
1) Site Settings ==> Create
2) Click on "Custom List" under the "Custom Lists" column.
• Name: CompanyEmployees
• Click OK
3) Settings ==-> List Settings
4) Click on "Advanced Settings" under the "General Settings" column
5) At the very top, change Allow management of content types?" to Yes.
6) Click on OK
7) Under "Content Types" click on "Add from existing site content types".
8) On the "Add Content Types:" page
• Select site content types from: Custom Content Types
• Add "Company Parent" and "Employee Child" content types.
• Click on OK
Let’s add some dummy data.
1. Click on the "CompanyEmployees" list
2. Click on the little arrow beside New. You should see this:
3. Select "Company Parent"
4. Add the following bogus company data:
• Name: ACME Corporation; CompanyId: 123
• Name: Bogus Enterprises: CompanyId: 456
5. Add bogus company employees to "ACME Corporation"
• Click on "ACME Corporation". This causes the folder to open.
• Add the following employees to the ACME Corporation by clicking on New ==-> Employee Child:
• Title: Jane Doe; EmployeeId: 111; Branch: Downtown
• Title: James White; EmployeeId: 222; Branch: Airport
• Click on "Bogus Enterprises". This causes the folder to open.
• Add the following employees to Bogus Enterprises by clicking on New ==-> Employee Child:
• Title: Judy Black; EmployeeId: 333; Branch: Main Street
• Title: Brandon Wiley; EmployeeId: 333; Branch: Riverside
• Add another employee to ACME:
This concludes configuration and data entry. Let us now use the SharePoint 2007 Object Model to get at this data.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
public class CompanyEmployees {
static void Main(string[] args) {
SPSite site = new SPSite("http://srvr/");
SPWeb web = site.AllWebs["/"];
SPList list = web.Lists["CompanyEmployees"];
foreach (SPListItem order in list.Folders) {
Console.WriteLine("Company ID : {0}", order["CompanyId"]);
Console.WriteLine("Company Name : {0}", order["Title"]);
SPQuery empItemsQuery = new SPQuery();
empItemsQuery.Folder = order.Folder;
SPListItemCollection empItems = list.GetItems(empItemsQuery);
foreach (SPListItem empItem in empItems) {
Console.WriteLine("\tEmployee ID {0}: {1} {2}",
empItem["EmployeeId"],
empItem["Title"],
empItem["Branch"]);
}
}
}
}
The above application will produce the following result:
Company ID : 123
Company Name : ACME Corporation
Employee ID 111: Jane Doe Downtown
Employee ID 222: James White Airport
Company ID : 456
Company Name : Bogus Enterprises
Employee ID 333: Judy Black Main Street
Employee ID 444: Brandon Wiley Riverside
Saturday, October 27, 2007
COMP-1536 & ACIT-1620 Fall 2007 week 09
Medhat Elmasry will be away attending a training course in downtown Vancouver. Here are some important notes on week 09:
Notes for COMP-1536 students
Notes for ACIT-1620 students
- Jason Harrison will be delivering the lectures on Tuesday October 30, 2007 at 10:30 AM and Friday November 2, 2007 at 12:30 PM. He will be introducing you to PHP.
- Medhat will not be present at the SET 1A lab on Monday October 29, 2007 at 1:30 PM. Students are expected to come to the lab session and use the time to work on assignment 3.
- Sets 1B, 1C, 1D, and 1E must attend labs with Jason Harrison as usual.
- You can post any questions as comments on my blog.
- There will be no lecture on Monday October 29, 2007 at 10:30 AM. Instead, Medhat will makeup this lecture in the labs during the following week.
- Brian Pidcock will be delivering the lecture on Friday November 2, 2007 at 1:30 PM on the topic of JavaScript functions.
- Medhat will not be present at SET 1A and SET 1B labs on Monday October 29, 2007 at 3:30 PM and Tuesday October 30, 2007 at 8:30 AM respectively. Students are expected to come to the lab session and use the time to work on assignment 3.
- You can post any questions as comments on my blog
Thursday, October 18, 2007
Creating "Calculated Field" columns in SharePoint 2007
You can pretty much use the same VBA syntax for calculated fields as in Excel. Here is a site that provides many examples of common formulas that can be used in SharePoint when defining "Calculated Field" columns.
Here is a formula that I created at work:
=IF(YEAR([Due Date])=1899,"No Due Date",TEXT([Due Date],"MM/dd/yyyy"))
Blank dates in SharePoint are assigned a date in year 1899. The above formula displays a message "No Due Date" for invalid dates or the valid date using format MM/dd/yyyy.
Here is a formula that I created at work:
=IF(YEAR([Due Date])=1899,"No Due Date",TEXT([Due Date],"MM/dd/yyyy"))
Blank dates in SharePoint are assigned a date in year 1899. The above formula displays a message "No Due Date" for invalid dates or the valid date using format MM/dd/yyyy.
Subscribe to:
Posts (Atom)