in

vbCity Blogs

New (temp) place for vbCity Blogs

Andy Bonner's Blog

My SharePoint titbits and other things that take my fancy.
  • Visual Studio 2005 is configuring the environment for first time use

    Copied from old Blog April 2007

    Every now & then I would get the first time launch message appearing when I was starting up VS 2005, which wasted lots of time & I finally got around to googling a solution.

    It turned out that it was a problem with using roaming profiles ( I switch between virtual machines quite often for various development requirements which I thinks what causes it) & I found the solutions in this MSDN article

    But I'll post it here as well for future reference

     


     

    When any one of the Visual Studio family of products is used with Windows Roaming Profiles, the first time launch message that says "Visual Studio 2005 is configuring the environment for first time use. This might take a few minutes." might appear on every session startup. This might cause unnecessary slowdowns in startup performance.

    To resolve this issue

    Click on the Tools > Options... Select "Import and Export Settings", and change the path under "Automatically save my settings to this file:" to a path that is NOT under the "My Documents" directory.

    Posted Dec 18 2008, 07:24 AM by Andy Bonner with no comments
    Filed under:
  • Get List of Site Users in InfoPath Form

    Copied from old Blog from Dec 2006

    I had the need the other day for a way of displaying a list of site users on an InfoPath form that the user can select from and came across this article on Jan Tielens' blog which I thought would do the trick. Unfortunately it was for SharePoint 2003 rather than 2007 so I had to play around a bit to get it working, & came up with 2 methods of accompishing it which I wanted to share with you.

    Create a New Visual Studio .Net project based on the InfoPath Form Template and call it ExampleGetSiteUsers.

    The first thing you'll need to do is go into Tools -> Form Options and set the forms security level to Full Trust

     

    Then create your main data source like so

     

    We'll need to create a DataConnection to the GetUserCollectionFromSite Method of the UserGroup SharePoint webservice.

    From the Visual Studio menu select Data -> Data Connections

     

    Click Add

     

    Select Create a new connection to Receive data then click Next

     

    Select Web service then click Next

     

    Enter http://YourServerName/_vti_bin/UserGroup.asmx for the webservice location making sure you put in your moss servers name then click next

    Select the GetUserCollectionFromSite method then click Next

     

    Click Next

     

    Enter a meaningful name for the data connection & ensure "Automatically retrieve data when the form is opened" is ticked. Then click Finish & close the data connections window. We now need to add a second data connection that will use the following XML file as it's source. Copy the code below to a new file & name it SiteUsersAndGroups.xml save it to a location on your machine that you'll remember.

    <?xml version="1.0" encoding="utf-8" ?>
    <SiteUsersAndGroups>
        <Users xmlns="<a href="http://schemas.microsoft.com/sharepoint/soap/directory/">http://schemas.microsoft.com/sharepoint/soap/directory/</a>">
            <User ID="" Sid="" Name="" LoginName="" Email="" Notes="" IsSiteAdmin="" IsDomainGroup=""/>
            <User ID="" Sid="" Name="" LoginName="" Email="" Notes="" IsSiteAdmin="" IsDomainGroup=""/>
        </Users>
    </SiteUsersAndGroups>
    

    From the Visual Studio menu select Data -> Data Connections Add a new connection to Receive data

     

    This time select XML Document as the source then click Next

    Enter the location of the XML document we just created then click Next

     

    Click Next

     

    Click Finish & close the Data Connections window

    Create a couple of DropDown Lists on your Form for the 2 fields in the main data source

     

    Go into the properties of the first Drop Down that is bound to our method1 field

     

    Select "Look up values from an external data source" & set the Data source to the connection we just created Click on the Select XPath for the entries

     

    Select the User repeating group & click OK

     

    Set the value to the ID and the Display name to the Name We now need to create yet another Data connection that we can use as the source for our second Drop Down. Normally you wouldn't need to do this as you could use the same source for both, but because I'm showing 2 methods which will be slightly different in the content they show we'll need a second connection. Follow exactly the same steps as we used to create the first data connection to an xml file, but name the connection SiteUsers as in the second method we'll be stripping out groups.

     

    Now we'll go into the properties of the second Drop Down & bind it to this new connection like so

     

     You'll now need to create a new class within your project called Users.cs which contains the following code

     

    //------------------------------------------------------------------------------
    // 
    //     This code was generated by a tool.
    //     Runtime Version:2.0.50727.42
    //
    //     Changes to this file may cause incorrect behavior and will be lost if
    //     the code is regenerated.
    // 
    //------------------------------------------------------------------------------
    
    
    using System.Xml.Serialization;
    
    
    //
    // This source code was auto-generated by xsd, Version=2.0.50727.42.
    //
    
    
    
    /// 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "<a href="http://schemas.microsoft.com/sharepoint/soap/directory/">http://schemas.microsoft.com/sharepoint/soap/directory/</a>", IsNullable = false)]
    public partial class Users
    {
    
    
        private User[] itemsField;
    
    
        /// 
        [System.Xml.Serialization.XmlElementAttribute("User")]
        public User[] Items
        {
            get
            {
                return this.itemsField;
            }
            set
            {
                this.itemsField = value;
            }
        }
    }
    
    
    /// 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class User
    {
    
    
        private string idField;
    
    
        private string sidField;
    
    
        private string nameField;
    
    
        private string loginNameField;
    
    
        private string emailField;
    
    
        private string notesField;
    
    
        private string isSiteAdminField;
    
    
        private string isDomainGroupField;
    
    
        /// 
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string ID
        {
            get
            {
                return this.idField;
            }
            set
            {
                this.idField = value;
            }
        }
    
    
        /// 
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Sid
        {
            get
            {
                return this.sidField;
            }
            set
            {
                this.sidField = value;
            }
        }
    
    
        /// 
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Name
        {
            get
            {
                return this.nameField;
            }
            set
            {
                this.nameField = value;
            }
        }
    
    
        /// 
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string LoginName
        {
            get
            {
                return this.loginNameField;
            }
            set
            {
                this.loginNameField = value;
            }
        }
    
    
        /// 
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Email
        {
            get
            {
                return this.emailField;
            }
            set
            {
                this.emailField = value;
            }
        }
    
    
        /// 
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Notes
        {
            get
            {
                return this.notesField;
            }
            set
            {
                this.notesField = value;
            }
        }
    
    
        /// 
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string IsSiteAdmin
        {
            get
            {
                return this.isSiteAdminField;
            }
            set
            {
                this.isSiteAdminField = value;
            }
        }
    
    
        /// 
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string IsDomainGroup
        {
            get
            {
                return this.isDomainGroupField;
            }
            set
            {
                this.isDomainGroupField = value;
            }
        }
    }
    

    Finally we're ready to write some code in the FormCode file Here's some I cooked up earlier which I've heavily commented so you can see what I'm doing.

    using Microsoft.Office.InfoPath;
    using System;
    using System.Xml;
    using System.Xml.XPath;
    using System.Xml.Serialization;
    
    
    namespace ExampleGetSiteUsers
    {
        public partial class FormCode
        {
            // NOTE: The following procedure is required by Microsoft Office InfoPath.
            // It can be modified using Microsoft Office InfoPath.
            public void InternalStartup()
            {
                this.EventManager.FormEvents.Loading += new LoadingEventHandler(FormEvents_Loading);
            }
    
    
            void FormEvents_Loading(object sender, LoadingEventArgs e)
            {
                //get an XPathNavigator to our webservice method
                XPathNavigator siteUsers = this.DataSources["GetUserCollectionFromSite"].CreateNavigator();
    
    
                //create the XmlNamespaceManager that will allow us to navigate the xml
                XmlNamespaceManager umanager = new XmlNamespaceManager(siteUsers.NameTable);
                umanager.AddNamespace("dfs", "<a href="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution">http://schemas.microsoft.com/office/infopath/2003/dataFormSolution</a>");
                umanager.AddNamespace("tns", "<a href="http://schemas.microsoft.com/sharepoint/soap/directory/">http://schemas.microsoft.com/sharepoint/soap/directory/</a>");
                //get the node that contains all the users from the call to the web service
                XPathNavigator allusers = siteUsers.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetUserCollectionFromSiteResponse/tns:GetUserCollectionFromSiteResult/tns:GetUserCollectionFromSite/tns:Users", umanager);
    
    
                //method 1
                //get an XPathNavigator to our data source used by the first Drop Down
                XPathNavigator siteUsersAndGroups = this.DataSources["SiteUsersAndGroups"].CreateNavigator();
    
    
                //create the XmlNamespaceManager that will allow us to navigate the xml
                //we can reuse this for our second data source in method 2 as the xml schema is identical
                XmlNamespaceManager dmanager = new XmlNamespaceManager(siteUsersAndGroups.NameTable);
                dmanager.AddNamespace("tns", "<a href="http://schemas.microsoft.com/sharepoint/soap/directory/">http://schemas.microsoft.com/sharepoint/soap/directory/</a>");
                //get the node within this data source that represents users
                XPathNavigator dusers = siteUsersAndGroups.SelectSingleNode("/SiteUsersAndGroups/tns:Users", dmanager);
    
    
                //fill this data source with the users returned by the web service call
                dusers.ReplaceSelf(allusers);
    
    
    
                //method 2
                //We'll start off by deserializing the xml node of users we got from the web service call
                //into our users class to make workingwith the data easier.
                Users su;
                XmlSerializer serializer = new XmlSerializer(typeof(Users));
                su = (Users)serializer.Deserialize(allusers.ReadSubtree());
    
    
                //create an XPathNavigator to the second data source we created from the xml document
                //i.e. the data source we're using for the second Drop Down
                //specifically the first User node
                XPathNavigator siteUser = this.DataSources["SiteUsers"].CreateNavigator().SelectSingleNode("/SiteUsersAndGroups/tns:Users/tns:User", dmanager);
                //create a clone of the this node so we can change the values
                XPathNavigator currentNode = siteUser.Clone();
    
    
                //We'll need to iterate through the users in our User class in
                //reverse order otherwise they'll appear in our drop down in decending order
                for (int i = su.Items.Length - 1; i >= 0; i--)
                {
                    User user = su.Items;
                    //Check each user to see if it's actually a group as we don't want those
                    if (user.IsDomainGroup == "False")
                    {
                        XPathNavigator newNode = currentNode;
                        //change some of the value on the clone, I'm only changing the 2 we need for this example
                        //but you could change them all
                        newNode.SelectSingleNode("/SiteUsersAndGroups/tns:Users/tns:User/@ID", dmanager).SetValue(user.ID);
                        newNode.SelectSingleNode("/SiteUsersAndGroups/tns:Users/tns:User/@Name", dmanager).SetValue(user.Name);
    
    
                        try
                        {
                            //insert the new node after the current one
                            currentNode.InsertAfter(newNode);
                        }
                        catch (Exception)
                        {
                        }
                        currentNode = newNode.Clone();
                    }
                }
                //this is the first blank node from our sample xml file so we need to get rid of it
                siteUser.DeleteSelf();
            }
        }
    }
    

    Go ahead & run the project. The first drop down will show all users & groups for your site, whilst the second will only show the users. You'll notice that the second Drop Down will be at a blank record at the end of the list of users & may be wondering why. The reason is that in our xml file that we used for the data connection there were 2 blank user nodes, which we need to have originally to tell InfoPath that User is a repeating group. Now that the connection is created we can edit the file that is stored within our project to get rid of the second blank record which will fix this up. To be able to edit the file you'll need to make sure that you haven't got manifest.xsf open otherwise you wont be able to open the file. From the solution window open SiteUsers & delete the second User node, save the file & rerun the project & voila...

  • How to keep SharePoint calendar expanded when switching months

    Ever get frustrated when looking at a SharePoint calendar and for a particular month you've clicked expand all then move to a different   month and find that you're back in collapsed view.

    Well you can change this by making some modifications to the CORE.JS file but keep in mind that you migh t have to redo this customization following any SharePoint service packs that you might apply.

    There's basically 2 functions  that  you need to change

    • GetMonthView -  called whenever you click the Expand All or Collapse all buttons.
    • MoveToViewDate  - called when you navigate to a new month

    Here's the new code that you'd need in those functions

    function GetMonthView(str)
    {
     //Added by Andy Bonner to memorize state
     SetCookie('ExpandCollapse',str,'');
     //Added by Andy Bonner to memorize state
    
    
     var wUrl=window.location.href;
     var ExpWeek=document.getElementById("ExpandedWeeksId");
     if(ExpWeek!=null)
      ExpWeek.value=str;
     else
      return ;
     SubmitFormPost(wUrl, true);
    }
    
    
    function MoveToViewDate(strdate, view_type)
    {
     //Added by Andy Bonner to keep expanded or collapsed state
     var ExpCol = GetCookie('ExpandCollapse');
     if(ExpCol != null)
     {
      var ExpWeek=document.getElementById("ExpandedWeeksId");
      if(ExpWeek!=null)
       ExpWeek.value=ExpCol;
     }
     //Added by Andy Bonner to keep expanded or collapsed state
    
    
    
     var wUrl=window.location.href;
     if (strdate !=null)
      wUrl=StURLSetVar2(wUrl,"CalendarDate",escapeProperly(strdate));
     if (view_type !=null)
      wUrl=StURLSetVar2(wUrl,"CalendarPeriod",view_type);
     SubmitFormPost(wUrl, true);
    }
    

  • SharePoint/MOSS Color Picker Custom Field

     Copied from old Blog March 2008

    Well it's been a long time since my last post and I though I'd better get my arse into gear and share some of the stuff I've been working on. As part of some development work I was doing for a colored SharePoint Calendar I had the need to allow users to select colors to have different types of Events displayed in and couldn't find a decent way of accomplishing this with the built in components of SharePoint, so I decided that this was an ideal candidate for a custom field type. Having made what I think is a useful addition to SharePoint I thought I'd share it with you. First I'll give you a little flavour of what it looks like before we dive into the code and how it all hangs together.

    New Edit View 1

    Here's how the field first looks in a New or Edit form

    New Edit View DropDown

    Here's some of the color choices available

    New Edit View 2

    And this is what it looks like once you've made some choices

    So thats what the field looks like when your using it but how does it display you might be wondering, well here's how you'd see it in a list view

    List View

    Yep lovely but not very practicle is it, the real power comes when you use this value either within code or the xslt of the DataView WebPart, then you can produce some quite stunning results.

    Color DataViewWebPart

    custom xslt using the field values

    Color Calendar

    Custom calendar views using the field values through code

    So Now that you've seen what you can do with it let's get into the code itself. In this example we have 5 files

    • SPColorsPickerFieldValue which inherits from SPFieldMultiColumnValue and holds the values and describes the properties for our field
    • SPColorsPickerField which inherits from SPFieldMultiColumn and is our field
    • SPColorsPickerFieldControl which inherits from BaseFieldControl and is the brains of the operation, basically the code behind for our ASCX
    • ControlTemplates_SPColorsPicker.ascx which defines a SharePoint RenderingTemplate element that tells it how to render our field in New or Edit mode
    • fldtypes_SPColorsPicker.xml which basically describes our field to SharePoint, telling it where it can be used, what it's called, what the assembly is called & also how it should be rendered in a list view

    So how do we create a project for this custom field you ask. Well just create a Class Library project within VS2005 & add references for Microsoft.SharePoint and Microsoft.SharePoint.Security which you'll find in C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI.

    You also need to sign the assembly with a strong name key. Then you'll need to add classes for the field, field value & field control. Each of these classes needs a unique guid attribute. Here's the 3 classes you need

    SPColorsPickerFieldValue (holds the values and describes the properties for our field)

     

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.SharePoint;
    using System.Runtime.InteropServices;
    
    
    namespace SPColorsPicker
    { 
    [CLSCompliant(false)]
    [Guid("7B5DF376-E7DB-4353-AD51-7C5B69C675D6")]
    [Serializable]
    public class SPColorsPickerFieldValue : SPFieldMultiColumnValue
    { 
    //how many properties are we storing
    private const int numberOfFields = 2;
    //required constructor
    public SPColorsPickerFieldValue() 
    : base(numberOfFields)
    {
    }
    //required constructor
    public SPColorsPickerFieldValue(string value) 
    : base(value)
    {
    }
    
    
    //property for storing the font color to use
    public string FontColor
    { 
    get
    { 
    if (string.IsNullOrEmpty(this[0])) 
    return "Black";
    else 
    return this[0];
    }
    set { this[0] = value; }
    }
    //property for storing the background color to use
    public string BackgroundColor
    { 
    get
    { 
    if (string.IsNullOrEmpty(this[1])) 
    return "White";
    else 
    return this[1];
    }
    set { this[1] = value; }
    }
    }
    }
    

    SPColorsPickerField (our field)

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    
    
    namespace SPColorsPicker
    { 
    [CLSCompliant(false)]
    [Guid("01FB13ED-33F3-4caa-8CCF-42DAE083291F")]
    public class SPColorsPickerField : SPFieldMultiColumn
    { 
    //required constructor
    public SPColorsPickerField(SPFieldCollection fields, string fieldName) 
    : base(fields, fieldName)
    {
    }
    //required constructor
    public SPColorsPickerField(SPFieldCollection fields, string typeName, string displayName) 
    : base(fields, typeName, displayName)
    {
    }
    //tell it which control to use for rendering this field
    public override BaseFieldControl FieldRenderingControl
    { 
    [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
    get
    { 
    BaseFieldControl fieldControl = new SPColorsPickerFieldControl();
    fieldControl.FieldName = this.InternalName;
    return fieldControl;
    }
    }
    //returns the value of this field
    public override object GetFieldValue(string value)
    { 
    if (String.IsNullOrEmpty(value)) 
    return null;
    return new SPColorsPickerFieldValue(value);
    }
    }
    }
    

    SPColorsPickerFieldControl (the brains)

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.SharePoint.WebControls;
    using System.Web.UI.WebControls;
    using System.Runtime.InteropServices;
    using System.Reflection;
    using System.Web.UI;
    using System.Drawing;
    
    
    namespace SPColorsPicker
    { 
    [CLSCompliant(false)]
    [Guid("F44DCD6A-D657-42e8-853A-ABC0713773C2")]
    public class SPColorsPickerFieldControl : BaseFieldControl
    { 
    protected DropDownList ddlBackground;
    protected DropDownList ddlFont;
    protected TextBox tbSampleText;
    private SPColorsPickerFieldValue fieldValue;
    protected override string DefaultTemplateName
    { 
    //Get the RenderingTemplate in the ascx file
    get { return "ColorsPicker"; }
    }
    public override object Value
    { 
    get
    { 
    EnsureChildControls();
    if (this.ControlMode != SPControlMode.Display)
    { 
    GetValues();
    }
    return fieldValue;
    }
    set
    { 
    EnsureChildControls();
    fieldValue = value as SPColorsPickerFieldValue;
    }
    }
    private void GetValues()
    { 
    //set this instances value to whats been selected
    fieldValue.FontColor = ddlFont.SelectedItem.Text;
    fieldValue.BackgroundColor = ddlBackground.SelectedItem.Text;
    }
    private void SetValues()
    { 
    //set the controls values to whats currently stored in the field for an existing item
    ddlFont.SelectedItem.Text = fieldValue.FontColor;
    ddlBackground.SelectedItem.Text = fieldValue.BackgroundColor;
    tbSampleText.ForeColor = Color.FromName(fieldValue.FontColor);
    tbSampleText.BackColor = Color.FromName(fieldValue.BackgroundColor);
    }
    protected override void OnInit(EventArgs e)
    { 
    //either get the value from an existing item or set it as a new value
    if (ControlMode == SPControlMode.Edit || ControlMode == SPControlMode.Display)
    { 
    if (this.ListItemFieldValue != null) 
    fieldValue = this.ListItemFieldValue as SPColorsPickerFieldValue;
    else 
    fieldValue = new SPColorsPickerFieldValue();
    }
    if (ControlMode == SPControlMode.New)
    { 
    fieldValue = new SPColorsPickerFieldValue();
    }
    base.OnInit(e);
    }
    protected override void OnLoad(EventArgs e)
    { 
    base.OnLoad(e);
    if (!Page.IsPostBack && ControlMode != SPControlMode.Display)
    { 
    //fill the DropDowns with the list of available colors
    List<string> allColors = new List<string>(Enum.GetNames(typeof(System.Drawing.KnownColor)));
    List<string> systemColors = new List<string>();
    foreach (MemberInfo member in (typeof(System.Drawing.SystemColors)).GetProperties())
    { 
    systemColors.Add(member.Name);
    }
    foreach (string color in allColors)
    { 
    if (!systemColors.Contains(color))
    { 
    this.ddlBackground.Items.Add(color);
    this.ddlFont.Items.Add(color);
    }
    }
    //register scripts to update the preview client side
    ClientScriptManager cs = this.Page.ClientScript;
    if (!cs.IsClientScriptBlockRegistered(this.GetType(), "ChangeColors"))
    { 
    StringBuilder csText = new StringBuilder();
    csText.Append(" <SCRIPT type=text/javascript>");
    csText.Append("function changeTextColor(dropdown, textboxID)");
    csText.Append("{");
    csText.Append("var x = document.getElementById(textboxID);");
    csText.Append("var myindex = dropdown.selectedIndex;");
    csText.Append("var SelValue = dropdown.options[myindex].value;");
    csText.Append("x.style.color = SelValue;");
    csText.Append("}");
    csText.Append("function changeBackgroundColor(dropdown, textboxID)");
    csText.Append("{");
    csText.Append("var x = document.getElementById(textboxID);");
    csText.Append("var myindex = dropdown.selectedIndex;");
    csText.Append("var SelValue = dropdown.options[myindex].value;");
    csText.Append("x.style.backgroundColor = SelValue;");
    csText.Append("}");
    csText.Append("</SCRIPT> ");
    cs.RegisterClientScriptBlock(this.GetType(), "ChangeColors", csText.ToString(), false);
    }
    SetValues();
    }
    }
    protected override void CreateChildControls()
    { 
    if (Field == null) 
    return;
    base.CreateChildControls();
    if (ControlMode == SPControlMode.Display) 
    return;
    //set the local vaiables
    ddlFont = (DropDownList)TemplateContainer.FindControl("ddlFont");
    ddlBackground = (DropDownList)TemplateContainer.FindControl("ddlBackground");
    tbSampleText = (TextBox)TemplateContainer.FindControl("tbSampleText");
    if (!Page.IsPostBack)
    { 
    //add attributes to call the javascript functions when we choose different colors from the dropdown box's
    //to update the preview client side
    string textboxID = this.tbSampleText.ClientID;
    ddlBackground.Attributes.Add("OnChange", string.Format("changeBackgroundColor(this,'{0}');", textboxID));
    ddlFont.Attributes.Add("OnChange", string.Format("changeTextColor(this,'{0}');", textboxID));
    }
    }
    //control how the field is rendered in display mode, doesn't overide list view display which is controlled
    //by the DisplayPattern in the fldtypes xml file
    protected override void RenderFieldForDisplay(HtmlTextWriter output)
    { 
    StringBuilder sbldr = new StringBuilder();
    sbldr.Append(" Sample Text");
    output.Write(sbldr.ToString());
    }
    }
    }
    

    I've commented the code so you can see what's going on so i'm not going to go into more detail here.  

    Compile your class library & install it in the GAC Now you can create the ascx file you'll need

    ControlTemplates_SPColorsPicker.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="ColorsPicker" runat="server"> 
    <Template> 
    <table> 
    <tr> 
    <td class="ms-formlabel"> 
    Background Color</td>
    <td> 
    <asp:DropDownList ID="ddlBackground" Width="200px" runat="server">
    </asp:DropDownList></td>
    </tr>
    <tr> 
    <td class="ms-formlabel"> 
    Text Color</td>
    <td> 
    <asp:DropDownList ID="ddlFont" Width="200px" runat="server">
    </asp:DropDownList></td>
    </tr>
    </table>
    <br />
    <asp:TextBox ID="tbSampleText" runat="server" Font-Bold="True" ReadOnly="True">SAMPLE TEXT</asp:TextBox>
    </Template>
    </SharePoint:RenderingTemplate>
    

     Then copy the ascx file to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES

    Open your class library using Lutz Roeder's Reflector to get hold of the assembly name which you'll need in the next file you need to create

    fldtypes_SPColorsPicker.xml

    xml version="1.0" encoding="utf-8" ?>
    <FieldTypes> 
    <FieldType> 
    <Field Name="TypeName">ColorsField>
    <Field Name="ParentType">MultiColumnField>
    <Field Name="TypeDisplayName">Colors PickerField>
    <Field Name="TypeShortDescription">Pick Background and Font ColorsField>
    <Field Name="UserCreatable">TRUEField>
    <Field Name="ShowInListCreate">TRUEField>
    <Field Name="ShowInDocumentLibraryCreate">TRUEField>
    <Field Name="ShowInColumnTemplateCreate">TRUEField>
    <Field Name="FieldTypeClass">SPColorsPicker.SPColorsPickerField, SPColorsPicker, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3a4554e68e310c34Field>
    <RenderPattern Name="DisplayPattern"> 
    <Switch> 
    <Expr> 
    <Column/>
    Expr>
    <Case Value="">
    Case>
    <Default> 
    <HTML> 0" HTMLEncode="TRUE"/>
    <HTML>; background-color: ]]>HTML>
    <Column SubColumnNumber="1" HTMLEncode="TRUE"/>
    <HTML>">Sample Text]]>HTML>
    Default>
    Switch>
    RenderPattern>
    FieldType>
    FieldTypes>
    

     Replace the value for FieldTypeClass with your assembly name then this file needs to be copied into C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML

    Now all you need to do is either recycle the application pool or do an IISReset to have this new field type available to your SharePoint Lists

    Create Column

  • 2 Level Top Navigation

     This is not my own work but something I picked up from a post a came across on MSDN that I thought would be useful, so i thought I'd blog it here so i knew where to find it in the future. Big Smile.

    Credit for this goes to Elizabeth Elizondo.

    All you need to do is add this after the PlaceHolderTopNavBar ContentPlaceHolder then tweak it to your requirements.

    <asp:ContentPlaceHolder ID="Sublinks" runat="server">
      <SharePoint:AspMenu
          ID="subMenu"
          Runat="server"
          DataSourceID="subSiteMap"
          EnableViewState="false"
          AccessKey="<%$Resources:wss,navigation_accesskey%>"
          Orientation="Horizontal"
            StaticDisplayLevels="1"
            StaticItemFormatString="{0}"
            SkipLinkText=""
            StaticSubMenuIndent="0"
            MaximumDynamicDisplayLevels="0"
            CssClass="ms-topNavContainer">
           <StaticMenuItemStyle CssClass="ms-topnav" ItemSpacing="0px"/>
           <StaticSelectedStyle CssClass="ms-topnavselected" />
           <StaticHoverStyle CssClass="ms-topNavHover" />
          </SharePoint:AspMenu>
    
    
          <asp:SiteMapDataSource
            SiteMapProvider="CombinedNavSiteMapProvider"
            ShowStartingNode="false"
            StartFromCurrentNode="false"
            StartingNodeOffset="1"        
            id="subSiteMap"
            runat="server"/>
     </asp:ContentPlaceHolder>
    

    Then you'l l end up with something like this

     2 Level Menu

  • Set SharePoint PeoplePicker Field mark 2

    Here's  an updated version of my PeoplePicker filling script that now uses the position of the  people picker rather than the field name to allow you to fill multiple people pickers easily.

    Note : If you tried my code & couldn't get it to work, it's because square brackets weren't displaying on this site so I've had to put a space after the integer when getting the value from the array to get it to show here.

     

    <script type="text/javascript">
    _spBodyOnLoadFunctionNames.push("fillDefaultValues");
    
    
    function fillDefaultValues()
    {
        //fill the  first people picture
     fillPeoplePickerWithCurrentUser(1);
     //fill th esecond people picker
     fillPeoplePickerWithCurrentUser(2);
    }
    
    
    function fillPeoplePickerWithCurrentUser(pickerNo)
    {
     var currentUser = getCurrentUser();
    
    
     if(currentUser != null)
     {
      var pp = getPickerImputElement(pickerNo);
      
      if(pp != null)
      {
       pp.innerHTML = currentUser;
      }
     }
    }
    
    
    
    function getPickerImputElement(pickerNo)
    {
     var result = '';
     var divs = document.getElementsByTagName('DIV');
     var j = 0;
    
    
     for(var i=0; i < divs.length; i++)
     {
      if(divs[i ].id.indexOf('UserField_upLevelDiv') > 0)
      {
       j++;
       
       if(j == pickerNo)
       {
        result = divs[i ];
        break;
       }
      }
     }
     return result;
    }
    
    
    function getCurrentUser()
    {
     var tags = document.getElementsByTagName('a');
     for(var i=0; i < tags.length; i++)
     {
      if(tags[i ].innerText.substr(0,7) == 'Welcome')
       return tags[i ].innerText.substr(8,tags[i ].innerText.length);
     }
    }
    </script>
    
    
     
    

  • How to get wz_tooltip.js working in SharePoint

    Came across an excellent javascript tooltip library by Walter Zorn that I thought would be a great additional to my SharePoint sites.  Unfortunately follow the instructions on his site would work fine in a normal Asp.Net app but not within the SharePoint environment.

    However I did eventually get it working when my grey matter kicked into gear and thought I better blog it quick before senility kicked in and I forgot it Wink

    Edit your master page and add a SharePoint:ScriptLink to the location of the wz_tooltip.js file i.e

    underneath

    <SharePoint:ScriptLink name="init.js" runat="server"/>
    

     add a new line with

    <SharePoint:ScriptLink name="Skullcrusher/wz_tooltip.js" runat="server"/>
    

     obviously just change it to match your location.

    This unfortunately isn't sufficient to get it working due to SharePoints quircks and I was getting "tt_aElt.0.style is null o not an object" errors.  This turned out to be due to the fact that the tooltip wasn't getting initialized properly and there is a simple fix.

    All you need to do is add a call to tt_Init in the onload of the body i.e. change

    <body class="body" onload="BLOCKED SCRIPT_spBodyOnLoadWrapper();">
    

    to

    <body class="body" onload="BLOCKED SCRIPT_spBodyOnLoadWrapper();tt_Init();">
    

    And that's it you can now use it in any SharePoint page. 

  • Get the Full user name in a web hosted InfoPath Form

     Copied from old blog December 2006

    Although you can easily get hold of the logged in users login name with

    this.Application.User.LoginName

    it's doesn't seem to be so easy to get hold of the users full name. It is however releatively easy to accomplish by making a call to one of the many webservices provided by MOSS, specifically the GetUserInfo method of the UserGroup webservice, which I'll guide you through now.

    You'll need to add the following class that I've created using the xsd.exe tool (it represents the details returned in the User node of the GetUserInfo Method) to your project.

     
    
    
    //------------------------------------------------------------------------------
    // 
    //     This code was generated by a tool.
    //     Runtime Version:2.0.50727.42
    //
    //     Changes to this file may cause incorrect behavior and will be lost if
    //     the code is regenerated.
    // 
    //------------------------------------------------------------------------------
    
    
    using System.Xml.Serialization;
    
    
    //
    // This source code was auto-generated by xsd, Version=2.0.50727.42.
    //
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://schemas.microsoft.com/sharepoint/soap/directory/", IsNullable = false)]
    public partial class User {
    
    
        private string idField;
    
    
        private string sidField;
    
    
        private string nameField;
    
    
        private string loginNameField;
    
    
        private string emailField;
    
    
        private string notesField;
    
    
        private string isSiteAdminField;
    
    
        private string isDomainGroupField;
    
    
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string ID {
            get {
                return this.idField;
            }
            set {
                this.idField = value;
            }
        }
    
    
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Sid {
            get {
                return this.sidField;
            }
            set {
                this.sidField = value;
            }
        }
    
    
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Name {
            get {
                return this.nameField;
            }
            set {
                this.nameField = value;
            }
        }
    
    
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string LoginName {
            get {
                return this.loginNameField;
            }
            set {
                this.loginNameField = value;
            }
        }
    
    
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Email {
            get {
                return this.emailField;
            }
            set {
                this.emailField = value;
            }
        }
    
    
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string Notes {
            get {
                return this.notesField;
            }
            set {
                this.notesField = value;
            }
        }
    
    
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string IsSiteAdmin {
            get {
                return this.isSiteAdminField;
            }
            set {
                this.isSiteAdminField = value;
            }
        }
    
    
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string IsDomainGroup {
            get {
                return this.isDomainGroupField;
            }
            set {
                this.isDomainGroupField = value;
            }
        }
    }
    

     

     

    You'll also need to set the forms security level to Full Trust.

    Now we need to create the data connection to the web service.

    Click Data -> Data Connections

     

    Click Add

     

    Select Create a new connection to Receive data then click Next

     

    Select Web service then click Next

     

    Enter http://YourServerName/_vti_bin/UserGroup.asmx for the webservice location making sure you put in your moss servers name then click next

     

    Select GetUserInfo from the list of available operations then click Next

     

    Infopath needs to get more info from the webservice operation which means you'll have to provide a valid Login name for it to query the webservice with, so click on the Set Sample Value button & input a user in the following format Domain\Login

     

    Click OK then click Next

     

    Click Next

     

    Click Next

     

    Enter a meaningful name for the data connection & ensure you remove the tick from Automatically retrieve data when the form is opened. Then click Finish & close the data connections window. Within your form code you can now add the using directive to System.Xml.Serialization & the following to the formloading event to retrieve the UserInfo details

    public void InternalStartup()
            {
                this.EventManager.FormEvents.Loading += new LoadingEventHandler(FormEvents_Loading);
            } 
    
    
            void FormEvents_Loading(object sender, LoadingEventArgs e)
            {
                //get hold of the datasource for the webservice operation
                DataSource ds = this.DataSources["GetUserInfo"];
                //Create an XPathNavigator to the node we have to set to query the method
                XPathNavigator userField = ds.CreateNavigator().SelectSingleNode("/dfs:myFields/dfs:queryFields/tns:GetUserInfo/tns:userLoginName", this.NamespaceManager);
                //Set the query value to the current users login name
                userField.SetValue(this.Application.User.LoginName);
                //execute the webservice operation
                ds.QueryConnection.Execute();
    
    
                //the data will now be in the datasource
                XPathNavigator userInfo = this.DataSources["GetUserInfo"].CreateNavigator();
                //add the namespaces so we can query the datasource
                XmlNamespaceManager umanager = new XmlNamespaceManager(userInfo.NameTable);
                umanager.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
                umanager.AddNamespace("tns", "http://schemas.microsoft.com/sharepoint/soap/directory/");
                //get hold of the node we're after
                XPathNavigator usernode = userInfo.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetUserInfoResponse/tns:GetUserInfoResult/tns:GetUserInfo/tns:User", umanager);
                //deserialize the contents of the node into our custom class
                User user;
                XmlSerializer serializer = new XmlSerializer(typeof(User));
                user = (User)serializer.Deserialize(usernode.ReadSubtree()); 
    
    
                //set the value of a field within out main data source i.e. the InfoPath form
                //to the users full name
                XPathNavigator field = this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:field1", this.NamespaceManager);
                field.SetValue(user.Name);
            }
    

     

    and voila!

     

     

     

    If you take a look at the User class you'll notice that there's other information available to you from the GetUserInfo method.

     

    Hope this information is useful to someone & saves them some time trying to figure this one out.

Copyright 1998-2009 vbCity.com LLC
Powered by Community Server (Non-Commercial Edition), by Telligent Systems