Part 3 – Sign Out/Sign in as a Different User
A project I am working on called for a custom implementation of the SharePoint Welcome menu control. Continue Reading →
A project I am working on called for a custom implementation of the SharePoint Welcome menu control. Continue Reading →
A project I am working on called for a custom implementation of the SharePoint Welcome menu control. The replacement control needed to provide the following:
I had to create a control that looked and behaved like the following:
The designers came up with some clean, semantic markup married with some jquery, for me to start from:
<div class="header">
<img class="header-logo" src="/images/header_logo.png" alt="" width="169" height="78" />
<div class="header-bar">
<div class="profile_menu">
<a href="#" class="profile_btn">
<span class="image"><img src="" style="width:20px;height:20px" /></span>
<span class="name">John Doe</span>
<span class="arrow"></span>
</a>
<div class="profile_dropdown">
<div class="dropdown_bkgrd">
<ul>
<li>Edit Profile</li>
<li>My Site</li>
<li>Log Out</li>
<li>Sign in as a Different User</li>
</ul>
</div>
</div>
</div>
</div>
</div>
This is part 2 of a three part series.
A project I am working on called for a custom implementation of the SharePoint Welcome menu control. The replacement control needed to provide the following:
I had to create a control that looked and behaved like the following:
The designers came up with some clean, semantic markup married with some jquery, for me to start from:
<div class="header">
<img class="header-logo" src="/images/header_logo.png" alt="" width="169" height="78" />
<div class="header-bar">
<div class="profile_menu">
<a href="#" class="profile_btn">
<span class="image"><img src="" style="width:20px;height:20px" /></span>
<span class="name">John Doe</span>
<span class="arrow"></span>
</a>
<div class="profile_dropdown">
<div class="dropdown_bkgrd">
<ul>
<li>Edit Profile</li>
<li>My Site</li>
<li>Log Out</li>
<li>Sign in as a Different User</li>
</ul>
</div>
</div>
</div>
</div>
</div>
This is part 1 of a three part series.
Generic Handlers (.ashx files) deployed to the _layouts directory are not directly supported by Visual Studio 2010 SharePoint projects like custom .aspx application pages are. This post will cover how to add them to your Visual Studio project and deploy them properly to the ISAPI folder.
Just wrapped up a project developing a custom metadata editor to plugin to the Colligo Contributor for SharePoint client.
If you aren’t familiar with Colligo, it’s a desktop client application/outlook add-in/explorer file manager, that enables users to save documents or emails directly to SharePoint, and be prompted for metadata at the time of saving.
Colligo reads the content type of the target lists/libraries, and generates a default form very similar to what SharePoint does with the default EditForm.aspx ListForm web part. If you don’t like the default form, or need to customize the metadata entry experience (for example custom validation, pulling from external data sources, inter-dependent controls), you can develop a custom editor and show your own Windows Forms-based form to the user.
The default Colligo Editor form, shown here when adding a new Announcement.
To start developing a custom editor, begin by installing Colligo Contributor, and obtaining your product and sdk keys from Colligo.
Create a new Visual Studio Class Library project, and add a reference to the Colligo dlls in the GAC.
Add the necessary using statements:
using Colligo;
using Colligo.Properties;
using Colligo.Util;
using Colligo.WML.MetaData;
Change your class to inherit from the ICustomEditor class:
namespace MyNamespace
{
public class MyCustomEditor : ICustomEditor
{
}
}
Implement the Interface methods:
namespace MyNamespace
{
public class MyCustomEditor : ICustomEditor
{
// SDK Key
private const string SDK_KEY = "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX";
#region ICustomEditor Members
public string GetSdkKey()
{
return SDK_KEY;
}
public EditorResult ShowEditor(IEditContext context)
{
// Show your form here
}
public ResolveConflictResult ShowResolveConflictDialog(IResolveConflictContext context)
{
return ResolveConflictResult.UseDefaultResolveDialog;
}
#endregion
}
}
In the ShowEditor method, this is where you can create an instance of a Windows Form, and call the ShowDialog method on it. You can also pre-validate and avoid showing your form for situations that are not appropriate.
public EditorResult ShowEditor(IEditContext context)
{
// Check if this is something we care about
if (!context.List.IsDocumentLibrary)
{
return EditorResult.UseDefaultEditor;
}
if (!string.Equals(context.List.Name, "Private Documents", StringComparison.CurrentCultureIgnoreCase) &&
!string.Equals(context.List.Name, "Public Documents", StringComparison.CurrentCultureIgnoreCase))
{
return EditorResult.UseDefaultEditor;
}
// Only show for Create/Edit (use the default Colligo form for Viewing)
if (context.EditorMode == EditorMode.Create || context.EditorMode == EditorMode.Edit)
{
using (myCustomWindowsForm myForm = new myCustomWindowsForm(context))
{
DialogResult createResult = DialogResult.None;
createResult = myForm.ShowDialog(context.Parent);
switch (createResult)
{
case DialogResult.Cancel:
return EditorResult.Cancel;
case DialogResult.OK:
return EditorResult.OK;
case DialogResult.No:
return EditorResult.UseDefaultEditor;
}
}
}
else
{
// View - Show the default editor
return EditorResult.UseDefaultEditor;
}
// Fall through
return EditorResult.OK;
}
Notice I am passing in the IEditContext instance into my form’s constructor. The IEditContext object has all the goodies in it, and will give you access to the list, the web, the content types, list item metadata, etc.).
Some basic things to consider are:
There are a number of ways/methods that may kick off the display of your form, and you need to consider each of these:
Following are some gotchas to be aware of:
Don’t make any assumptions about any of the items in the IEditContext object. ContentTypes may be null, Fields may not exist or be null, other relevant ILists in the Web may not be synchronized locally, and will be null, etc., etc., etc. Check everything for null first, and test everything that returns a collection/array for Count and Length > 0. If there are fields/lists/lookup column values that your form expects, check for the existence of these things right away, and exit if you don’t find them.
If your form is called via the Save As dialog from an application (or via the FileManager), the ParentWindow handle may not be valid, so be careful with the ShowDialog(IWin32Window) overload, which threw a System.ComponentModel.Win32Exception for me. I had to wrap my ShowDialog(context.Parent) in a try>catch, and then try it without any parameters (ShowDialog() ).
If you are using any custom field types, be really careful to make sure and store the data in the proper format. My customer was using a couple of custom field types found on CodePlex, and one of them extended the Lookup field, and it took me a few traces with Fiddler to figure out that it wanted its values in lookup column format (“52;#ItemName”);
If you have any lookup columns that are defined in higher-level sites, and you are using those site columns in lists located in subsites, then Colligo will not be able to see the lookup values. In order to implement these scenarios, you will have to force your users to synchronize the higher level sites as well as the subsites.