<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Adventures in Consulting</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/valdon/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/valdon/feed.xml</link>
    <description>This is a place for me to share those little gems one finds when doing consulting work.  Since I focus mainly on SharePoint Server, most of the posts will cover topics relating to SharePoint.</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:41:40 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Solving the “User cannot be found” error with SPFile.Author</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/solving-the-user-cannot-be-found-error-with-spfile-author</link>
      <pubDate>Thu, 16 Jun 2011 09:05:00 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2011/06/16/solving-the-user-cannot-be-found-error-with-spfile-author/</guid>
      <description><![CDATA[I ran into a bug today that was a bit unusual.&nbsp; We have a custom ASP.NET page that shows...]]></description>
      <content:encoded><![CDATA[<p>I ran into a bug today that was a bit unusual.&nbsp; We have a custom ASP.NET page that shows information from a custom list in SharePoint 2007.&nbsp; That page shows details, including the Author, for attachments.&nbsp; On one particular list item, users started getting a &ldquo;User cannot be found&rdquo; error whey they tried to view it with our custom page.&nbsp; The stack trace showed that it was getting the error in Microsoft.SharePoint.SPFile.get_Author().</p>
<p>It turns out that SPFile stores the user as a login name and tries to resolve the name using SPWeb.SiteUsers, which throws an error if the login name is not found.&nbsp; The issue was, in this case, the attachment author had been removed from Active Directory and was no longer in SharePoint&rsquo;s user list, hence the error.</p>
<p>The fix is to go directly to the SPFile properties and get the login name.&nbsp; Since we can no longer resolve the login name to a user display name, we just display the login name.</p>
<pre class="csharpcode"><span class="kwrd">string</span> GetAuthorName(<span style="color: #4bacc6;">SPFile</span> file)
{
    <span style="color: #4bacc6;">SPUser</span> author = <span class="kwrd">null</span>;
    <span class="kwrd">try</span> { author = file.Author; } <span class="kwrd">catch</span> { }
    <span class="kwrd">return</span> (author == <span class="kwrd">null</span>) ? (<span class="kwrd">string</span>)file.Properties[<span class="str">"vti_author"</span>] : author.Name;
}</pre>
]]></content:encoded>
    </item>
    <item>
      <title>Remove List Item Menu Options with Javascript</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/remove-list-item-menu-options-with-javascript</link>
      <pubDate>Tue, 08 Jun 2010 12:03:37 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2010/06/08/remove-list-item-menu-options-with-javascript/</guid>
      <description><![CDATA[SharePoint has a lot of JavaScript code to manage UI, and a lot of customization can be done by...]]></description>
      <content:encoded><![CDATA[<p>SharePoint has a lot of JavaScript code to manage UI, and a lot of customization can be done by modifying out-of-box JavaScript.&#160; However, modifying system files is not a good idea.&#160; Instead, you usually will want to copy the file and make your custom changes there.</p>  <p>One other way to make customizations is to “override” functions using pointers.&#160; In our case, we didn’t want the “Manage Permissions” options to show up in the list item menu for most users.&#160; Just removing the “Manage Permissions” permission for those user groups didn’t work because they also have the “Enumerate Permissions” permission, which is needed for general access to the list.&#160; The “Manage Permissions” menu option shows up for either of these.</p>  <p>So, there is a handy function called AddManagePermsMenuItem in the core.js file that you can “override”.&#160; In this example, I’m checking to see if the user has “Manage Permission” permission (0x20000000 bit is set):</p>  <p></p> <font color="#0000ff"><font color="#0000ff">     <p align="left"><font size="2" face="Courier New"></font></p>     <font size="2"><font face="Courier New">&#160;&#160;&#160; var <font color="#000000">original_AddManagePermsMenuItem = AddManagePermsMenuItem;</font>           <br /><font color="#000000">&#160;&#160;&#160; AddManagePermsMenuItem</font> = <font color="#0000ff">function</font></font></font><font color="#000000" size="2" face="Courier New">(m, ctx, listId, url) {        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </font><font face="Courier New"><font size="2"><font color="#0000ff">if</font><font color="#000000"> (!HasRights(0x0, 0x2000000))</font>           <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </font><font color="#0000ff" size="2">return</font></font><font color="#000000" size="2" face="Courier New">;        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; </font></font></font><font size="2"><font color="#000000" face="Courier New">original_AddManagePermsMenuItem(m, ctx, listId, url);      <br />&#160;&#160;&#160; }</font></font>   <p align="left"><font size="2" face="Courier New"></font></p>  <p>First it saves a pointer to the current function, then replaces the function with an anonymous function.&#160; The anonymous function checks the rights and returns if the user doesn’t have “Manage Permission” rights.&#160; If the user does, it calls the original AddManagePermsMenuItem through the pointer we saved earlier.</p>  <p>Place this script in your master page after the inclusion of core.js and any list view that uses that master page will no longer show the “Manage Permissions” option for most users.</p>]]></content:encoded>
    </item>
    <item>
      <title>Customizing ASP.NET Validators without using the CustomValidator Control</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/customizing-asp-net-validators-without-using-the-customvalidator-control</link>
      <pubDate>Thu, 11 Feb 2010 08:32:51 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2010/02/11/customizing-asp-net-validators-without-using-the-customvalidator-control/</guid>
      <description><![CDATA[This isn’t a SharePoint tip, per se, but it is an interesting way to expand on what the default...]]></description>
      <content:encoded><![CDATA[<p>This isn’t a SharePoint tip, per se, but it is an interesting way to expand on what the default RequiredFieldValidator control does for you.</p>  <p>We already had validation in our custom pages using the RequiredFieldValidator control, and it was working well, however, our customer wanted the behavior to be different than the default of displaying an asterisk next to required fields.&#160; Instead, it needed to highlight the required fields by shading them a light red (I think that’s called pink… anyway…).&#160; My first thought was to change to use the CustomValidator control, which would allow us to have custom client-side script.&#160; However, that would mean that I would need to implement the validation logic in JavaScript for the client and again in C# for the server.&#160; The standard RequiredFieldValidator class does both client and server-side validation automatically, which is nice.</p>  <p>So, instead, I remembered that you can mess with function pointers in JavaScript and essentially override whatever functions you want.&#160; With a little poking around using IE 8’s developer add-in, I found that the function I wanted to “override” was the ValidatorUpdateDisplay function.&#160; Within this function, I could add in the code to highlight the field any way I wanted.</p>  <p>So, here’s what the JavaScript looks like.</p>  <pre class="csharpcode"><span class="kwrd">var</span> Original_ValidatorUpdateDisplay = ValidatorUpdateDisplay;
ValidatorUpdateDisplay = <span class="kwrd">function</span>(val) {
    Original_ValidatorUpdateDisplay(val);
    <span class="kwrd">var</span> valControl = document.getElementById(val.controltovalidate);
    <span class="kwrd">if</span> (valControl) {
        valControl.style.backgroundColor = val.isvalid ? 0xFFFFFF : 0xFFE0D6;
    }
}</pre>
<style type="text/css">


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Place this within your &lt;form&gt; section in a &lt;script&gt; block and your new function will get called anytime there is validation done (I put it in the master page for our custom forms).&#160; Change the code in the “if (valControl)…” block to do whatever highlighting you want.&#160; Note that the effect you get from this is that the fields that don’t pass validation will be shaded light red, but as soon as the user enters valid data and the field loses the focus, it will change it back to a white background, giving the user instant visual validation.</p>

<p>This code does two things:</p>

<p>1. It saves off the function pointer of the original ValidatorUpdateDisplay function into a variable called Original_ValidatorUpdateDisplay.</p>

<p>2. It replaces the original function pointer with a new function pointer (defined in-line as an anonymous method).</p>

<p>This way, the new method can call the original method and not have to reproduce all of its code.</p>]]></content:encoded>
    </item>
    <item>
      <title>FF at the End of a Content Type ID Kills Update Propagation</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/ff-at-the-end-of-a-content-type-id-kills-update-propagation</link>
      <pubDate>Fri, 04 Dec 2009 16:25:14 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2009/12/04/ff-at-the-end-of-a-content-type-id-kills-update-propagation/</guid>
      <description><![CDATA[I just spent a couple of hours tracking down an issue where our content type update code wasn’t...]]></description>
      <content:encoded><![CDATA[<p>I just spent a couple of hours tracking down an issue where our content type update code wasn’t working for some content types.&#160; The problem ended up being that one content type in the hierarchy had a content type ID that ended with “FF” (such as “0x0100EBE43BB291D8438f94E2C48C129366FF”).&#160; None of this type’s child content types were getting updated (for example, the content type with ID “0x0100EBE43BB291D8438f94E2C48C129366FF01” was not updated).</p>  <h2>Details</h2>  <p>When updating content types and you want those updates to push down (propagate) to child content types, you need to either do that through the SharePoint UI, or write code.&#160; In our case, we have code in the feature receiver that adds new site columns to content types as needed.&#160; We have a hierarchy of content types and when we update a base content type, we want those changes to be pushed down to their children, their children’s children and so on.&#160; We do this using the SPContentType’s Update(true) method.</p>  <p>Even with this, none of the children of one specific content type were getting updated.&#160; After scouring the code for clues and trying various ways of updating, I started to wonder if the ID was “special” in any way since ID’s are parsed by SharePoint (for example, a “00” tells SharePoint that the preceding characters represent the ID of a base content type).&#160; I noticed that it ended in “FF”; all of the other types that were propagating correctly ended with other characters.&#160; So, I changed it to end in “0E”, reactivated the feature, and the propagation worked!</p>  <p>So, it appears that somewhere in the SharePoint code that updates content types, “FF” has some special meaning, telling it, “stop here, don’t propagate any further.”</p>]]></content:encoded>
    </item>
    <item>
      <title>Creating Several List Instances in a Single Feature</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/creating-several-list-instances-in-a-single-feature</link>
      <pubDate>Thu, 06 Aug 2009 10:05:00 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2009/08/06/creating-several-list-instances-in-a-single-feature/</guid>
      <description><![CDATA[I’m not sure why I didn’t find this earlier, but I have always put a single list instance definition...]]></description>
      <content:encoded><![CDATA[<P>I’m not sure why I didn’t find this earlier, but I have always put a single list instance definition into a single feature.&nbsp; However, I recently had to put together several inter-related lists into a feature (no single list was useful by itself).&nbsp; The first approach was to create each list instance as a hidden feature and then have a visible feature that activated the hidden features through code in the feature receiver.</P>
<P>This just didn’t seem like a good way to maintain this going forward since I ended up with several hidden features, which I don’t really care for (I’d rather everything be visible).&nbsp; So I tried putting all the list instances into one feature, with subfolders for each list, but I saw strange behavior.&nbsp; Lists would have fields included that were part of another list definition.&nbsp; What was going on?</P>
<P>So I started doing some hunting around and it turns out that you can do what I wanted, you just couldn’t take the list templates as they were straight from an export (I always make my lists by creating them in the SharePoint UI and then exporting using SharePoint export or another tool).</P>
<P>First, you need to change the <STRONG>Type</STRONG> attribute of the <STRONG>ListTemplate</STRONG> element in the <STRONG>elementManifest.xml</STRONG> file and, in the same file, change the <STRONG>TemplateType</STRONG> attribute of the <STRONG>ListInstance</STRONG> element to match the new Type value.&nbsp; It turns out that the ListTemplate Type value only needs to be unique within the feature, so make all of your Type values different (I ended up making all the Type values different across the entire solution so I could easily move list definitions between features until I got ready to release).&nbsp; It seems that the default export type value is always 100, which confused SharePoint into adding fields from multiple templates with that Type within the same feature.</P>]]></content:encoded>
    </item>
    <item>
      <title>Removing Extra Workflow Status Column in Default View</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/removing-extra-workflow-status-column-in-default-view</link>
      <pubDate>Tue, 05 May 2009 22:25:48 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2009/05/05/removing-extra-workflow-status-column-in-default-view/</guid>
      <description><![CDATA[When SharePoint starts a workflow on a list for the first time, it has this annoying behavior of...]]></description>
      <content:encoded><![CDATA[<p>When SharePoint starts a workflow on a list for the first time, it has this annoying behavior of adding a workflow status column to the default view of the list.&nbsp; Often times, this information is of no practical use for end users.&nbsp; Unfortunately, there appears to be no way of getting rid of this behavior.&nbsp; So instead, you have to either remove it by hand after the first instance has started, or write custom code.&nbsp; Luckily the code is fairly simple and can be placed anywhere you want, including inside of a custom code activity within the workflow that is started.</p> <p>Here's the type of code you need:</p><pre class="csharpcode"><span class="rem">// In our case, the internal column name is the first 8 characters of the<br>// list name followed by " Workflow"</span>
<span class="kwrd">string</span> colName = (WorkflowItemList.Title + <span class="str">" Workflow"</span>).Substring(0, 8);
SPView defaultView = YourList.DefaultView;
<span class="kwrd">if</span> (defaultView.ViewFields.SchemaXml.Contains(<span class="str">"\""</span> + colName + <span class="str">"\""</span>))
{
    defaultView.ViewFields.Delete(colName);
    defaultView.Update();
}
</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Note that I <strong><em>think</em></strong> the internal column name is always the first 8 characters of the list name, but if you have multiple workflows on the same list, it may be different (you may need to export your list and look at the manifest.xml to find the internal field name).&nbsp; If you find it is different,&nbsp; you could either hard code the column name or you could loop through all the FieldsRefs in the view and remove any that have a type of "WorkflowStatus".&nbsp; In any case <strong><em>do not remove the Field from the SPList</em></strong> (this will crash your workflows!); just remove the FieldRef from the SPView.&nbsp; Once it's gone, SharePoint won't try and add it back unless you remove the workflow association and add it back in.</p>
<p><em><strong>UPDATE:</strong> the internal column name is actually the first 8 characters of the workflow name, which in our case was using the list name followed by " Workflow", but is not always the case.&nbsp; Change the first line in the sample code to retrieve the workflow name, or hard code the name if it is always the same in your case.</em></p>
<p><em>Also, one other thing I tried after this was to explicitly add the workflow status field into the list definition, copying the Field definition directly from the exported list definition manifest file, thinking that we would just preempt SharePoint and add the field ourselves, leaving it out of the default view.&nbsp; Alas, this did not work as SharePoint, once again, outsmarted us by adding its own field to the column and the default view.</em></p>]]></content:encoded>
    </item>
    <item>
      <title>Using Calculated Fields to Pad Numbers with Leading Zeros</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/using-calculated-fields-to-pad-numbers-with-leading-zeros</link>
      <pubDate>Tue, 05 May 2009 16:29:00 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2009/05/05/using-calculated-fields-to-pad-numbers-with-leading-zeros/</guid>
      <description><![CDATA[Just a quick note on one way to put leading zeros in a SharePoint list field using a Calculated...]]></description>
      <content:encoded><![CDATA[<P>Just a quick note on one way to put leading zeros in a SharePoint list field using a Calculated Field.&nbsp; A client wanted a column to show the list item's name, followed by a number that was left-padded with zeros to two digits, like:</P>
<BLOCKQUOTE>
<P>Addendum-01</P>
<P>Addendum-02</P>
<P>...</P></BLOCKQUOTE>
<P>Turns out there's no function (at least that I could find) to do this, but using CONCATENATE, REPT and LEN function, I could do it as follows:</P>
<P>Replace [Item Name] with the field name that contains the name and [Item Number] with the field name that contains the item number.</P><PRE class=csharpcode>=CONCATENATE([Item Name],<SPAN class=str>"-"</SPAN>,REPT(<SPAN class=str>"0"</SPAN>,2-LEN([Item Number])),[Item Number])</PRE>
<P>The REPT function will repeat a given string a specified number of times.&nbsp; By subtracting the length of the number from 2, I could tell it how many leading zeros were needed.</P>
<P>One caveat to this is that I'm not sure if it works with numbers longer than the digit count we want (in this case, greater than 99).&nbsp; I'm not sure of the behavior of REPT with negative numbers passed in.&nbsp; In my client's, it isn't an issue, but if you need to, you could add an IF function that checks if it is negative and uses zero if it is.</P>
<STYLE type=text/css>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</STYLE>]]></content:encoded>
    </item>
    <item>
      <title>How to work around bugs in the SPGridView control</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/how-to-work-around-bugs-in-the-spgridview-control</link>
      <pubDate>Wed, 11 Mar 2009 20:11:15 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2009/03/11/how-to-work-around-bugs-in-the-spgridview-control/</guid>
      <description><![CDATA[SharePoint has a little known web control called SPGridView.&nbsp; This control can give you a...]]></description>
      <content:encoded><![CDATA[<p>SharePoint has a little known web control called SPGridView.&nbsp; This control can give you a SharePoint list-like view of data from any data source you can bind to (from a database or other sources).&nbsp; It also has features to sort, filter and group the data in much the same way users can with SharePoint lists.&nbsp; For more information on how to use this, Paul Robinson has two great posts: <strong><em>SPGridView and SPMenuField: Displaying custom data through SharePoint lists</em></strong> <a href="https://blogs.msdn.com/powlo/archive/2007/02/25/displaying-custom-data-through-sharepoint-lists-using-spgridview-and-spmenufield.aspx" target="_blank">Part 1</a> and <a href="https://blogs.msdn.com/powlo/archive/2007/03/23/adding-paging-to-spgridview-when-using-custom-data-sources.aspx" target="_blank">Part 2</a>.&nbsp; In addition, Robert Fridén has a good post on <a href="https://www.sharepointblogs.com/bobsbonanza/archive/2007/07/02/filtering-with-spgridview.aspx" target="_blank">Filtering with SPGridView</a>.&nbsp; However, there are two bugs that can be annoying and cause confusion to users:</p> <ul> <li>When both filtering and grouping are enabled, the first group title row sometimes disappears.  <li>When both sorting and filtering are enabled, the sort indicator arrow image will sometimes appear in the wrong column.</li></ul> <p>Working around either of these bugs requires you to create your own web control based on SPGridView and overriding the CreateChildControls method.&nbsp; Here is the full code listing for the solution to work around both bugs.</p><pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.Globalization;
<span class="kwrd">using</span> System.Reflection;
<span class="kwrd">using</span> System.Web.UI;
<span class="kwrd">using</span> System.Web.UI.WebControls;

<span class="kwrd">using</span> Microsoft.SharePoint.WebControls;

<span class="kwrd">namespace</span> AdventuresInConsulting
{
    <span class="kwrd">public</span> <span class="kwrd">class</span> GridViewControl : SPGridView
    {
        <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">int</span> CreateChildControls(System.Collections.IEnumerable dataSource, <span class="kwrd">bool</span> dataBinding)
        {
            <span class="rem">// Due to a bug in SPDataView, we need to reset the private field previousGroupFieldValue so the </span>
            <span class="rem">// first grouping row title will consistently show up</span>
            FieldInfo fieldInfo = <span class="kwrd">typeof</span>(SPGridView).GetField(<span class="str">"previousGroupFieldValue"</span>,
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            <span class="kwrd">if</span> (fieldInfo != <span class="kwrd">null</span>)
                fieldInfo.SetValue(<span class="kwrd">this</span>, <span class="kwrd">null</span>);

            <span class="kwrd">int</span> returnValue = <span class="kwrd">base</span>.CreateChildControls(dataSource, dataBinding);

            <span class="rem">// Fix up a bug in the SPGridView where it is putting the sort arrow indicator on the wrong</span>
            <span class="rem">// column if AllowFiltering is true</span>
            <span class="kwrd">if</span> (<span class="kwrd">this</span>.AllowFiltering &amp;&amp; <span class="kwrd">this</span>.HeaderRow != <span class="kwrd">null</span> &amp;&amp; !<span class="kwrd">string</span>.IsNullOrEmpty(<span class="kwrd">this</span>.SortExpression))
            {
                List&lt;<span class="kwrd">string</span>&gt; filterFields = <span class="kwrd">new</span> List&lt;<span class="kwrd">string</span>&gt;(<span class="kwrd">this</span>.FilterDataFields.Split(<span class="str">','</span>));
                <span class="kwrd">if</span> (<span class="kwrd">this</span>.AllowGrouping) filterFields.Insert(0, <span class="kwrd">string</span>.Empty);

                <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; <span class="kwrd">this</span>.HeaderRow.Cells.Count; i++)
                {
                    DataControlFieldHeaderCell cell = <span class="kwrd">this</span>.HeaderRow.Cells[i] <span class="kwrd">as</span> DataControlFieldHeaderCell;
                    <span class="kwrd">if</span> (cell != <span class="kwrd">null</span>)
                    {
                        <span class="rem">// Find the sort image control</span>
                        Image sortImage = <span class="kwrd">null</span>;
                        <span class="kwrd">foreach</span> (Control c <span class="kwrd">in</span> cell.Controls)
                        {
                            sortImage = c <span class="kwrd">as</span> Image;
                            <span class="kwrd">if</span> (sortImage != <span class="kwrd">null</span> &amp;&amp; sortImage.ImageUrl == <span class="kwrd">this</span>.SortDirectionImageUrl)
                                <span class="kwrd">break</span>;
                        }

                        <span class="rem">// If this field is filterable, make sure the menu image is correct</span>
                        <span class="kwrd">if</span> (i &lt; filterFields.Count &amp;&amp; filterFields[i].Trim() != <span class="kwrd">string</span>.Empty)
                        {
                            <span class="rem">// If there is also an image control, remove it (we'll add it back in the right place)</span>
                            <span class="kwrd">if</span> (sortImage != <span class="kwrd">null</span>) cell.Controls.Remove(sortImage);

                            <span class="rem">// Find the menu control and add or remove the image in there as needed</span>
                            <span class="kwrd">foreach</span> (Control c <span class="kwrd">in</span> cell.Controls)
                            {
                                <span class="kwrd">if</span> (c <span class="kwrd">is</span> Microsoft.SharePoint.WebControls.Menu)
                                {
                                    Microsoft.SharePoint.WebControls.Menu menu = c <span class="kwrd">as</span> Microsoft.SharePoint.WebControls.Menu;
                                    <span class="kwrd">if</span> (<span class="kwrd">this</span>.SortExpression.Equals(<span class="kwrd">this</span>.Columns[i].SortExpression, StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        <span class="rem">// Make sure it has the sort indicator</span>
                                        menu.RightImageUrl = <span class="kwrd">this</span>.SortDirectionImageUrl;
                                        menu.ImageTextSpacing = <span class="kwrd">new</span> Unit(<span class="str">"2px"</span>, CultureInfo.InvariantCulture);
                                    }
                                    <span class="kwrd">else</span> <span class="kwrd">if</span> (menu.RightImageUrl == <span class="kwrd">this</span>.SortDirectionImageUrl)
                                    {
                                        <span class="rem">// Make sure it doesn't have the sort indicator</span>
                                        menu.RightImageUrl = <span class="kwrd">null</span>;
                                        menu.ImageTextSpacing = Unit.Empty;
                                    }
                                }
                            }
                        }
                        <span class="kwrd">else</span>
                        {
                            <span class="kwrd">if</span> (<span class="kwrd">this</span>.SortExpression.Equals(<span class="kwrd">this</span>.Columns[i].SortExpression, StringComparison.InvariantCultureIgnoreCase))
                            {
                                <span class="rem">// Make sure there is a sort image</span>
                                <span class="kwrd">if</span> (sortImage == <span class="kwrd">null</span>)
                                {
                                    sortImage = <span class="kwrd">new</span> Image();
                                    sortImage.ImageUrl = <span class="kwrd">this</span>.SortDirectionImageUrl;
                                    sortImage.Style[HtmlTextWriterStyle.MarginLeft] = <span class="str">"2px"</span>;
                                    cell.Controls.Add(sortImage);
                                }
                            }
                            <span class="kwrd">else</span> <span class="kwrd">if</span> (sortImage != <span class="kwrd">null</span>)
                            {
                                <span class="rem">// Remove the sort image if it exists</span>
                                cell.Controls.Remove(sortImage);
                            }
                        }
                    }
                }
            }

            <span class="kwrd">return</span> returnValue;
        }
    }
}
</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<h4>Fixing the group title row disappearance</h4>
<p>Making it so that the first group title row doesn't disappear is fairly simple.&nbsp; I noticed that this problem occurred if the filter or sort caused the first group in the new results to be the same as the last group from the previous results.&nbsp; This led me to look at how SPGridView was checking for the start of a new group.&nbsp; Sure enough, it was just checking to see if the value of the group field in the current row was different from the group field value the last time it detected a change.&nbsp; It saves the last group value in a field called previousGroupFieldValue.&nbsp; That value was being preserved between calls (presumably so that paging will work correctly).&nbsp; The easy fix is to reset the last group value.&nbsp; The problem was that the value was accessed through a private field.&nbsp; Of course, thanks to .NET reflection, we won't let that stand in our way.&nbsp; We just grab&nbsp; the FieldInfo for previousGroupFieldValue and then forcibly set the value.</p>
<p>NOTE: you may need to modify this slightly if paging is enabled.&nbsp; You probably only want to reset it if the page has not changed.</p>
<h4>Fixing the sort indicator arrow image</h4>
<p>Fixing the sort indicator arrow image is the more difficult of the two work arounds.&nbsp; I had hoped to recreate the CreateChildControls method of SPGridView and just avoid the image from coming up in the wrong place.&nbsp; However, it turns out that SPGridView calls its base class CreateChildControls method and there is no way in C# for a derived class to call its base's base class methods.&nbsp; So, rather than trying to recreate a whole chain of CreateChildControls methods, I just let SPGridView put the arrows where it wanted to and then fixed them up later.</p>
<p>The code loops through all of the column headers and looks for the sort indicator image either as a standalone Image control, or as the RightImageUrl of the column menu's title.&nbsp; We remove the image where it doesn't belong and add the image where it does belong.</p>
<p>Note on this bug: the issue arises because enabling grouping causes a hidden column to be added to the front of the grid and the code logic SPGridView uses to decide which column to put the filter indicator on is off by one.&nbsp; You'd think it'd be off to the left, but it is actually off to the right because whoever wrote the code knew there was a hidden column, but they overcompensated for it (kind of feels like being in a car with a kid learning to drive with power steering for the first time).</p>]]></content:encoded>
    </item>
    <item>
      <title>Using Both Field and FieldRef in InfoPath List Loses Data</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/using-both-field-and-fieldref-in-infopath-list-loses-data</link>
      <pubDate>Fri, 23 Jan 2009 16:13:50 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2009/01/23/using-both-field-and-fieldref-in-infopath-list-loses-data/</guid>
      <description><![CDATA[It appears that if you have both a Field and a FieldRef definition in your SharePoint list...]]></description>
      <content:encoded><![CDATA[<p>It appears that if you have both a Field and a FieldRef definition in your SharePoint list definition file that includes XML (InfoPath) field promotion, you can no longer update the field through the list; you must do it through the XML only.</p> <p>I ran into this interesting bug that took quite some time to track down.&nbsp; We have several site definitions that have a number of SharePoint custom lists that use a shared set of site columns.&nbsp; One of the custom lists is a document library containing InfoPath XML files that are edited using Web-based forms.&nbsp; The list definition includes fields that are "promoted" (synchronized with) the InfoPath XML file such as:</p><pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">Field</span> <span class="attr">ID</span><span class="kwrd">="{12345678-9ABC-DEF0-1234-56789ABCDEF0}"</span>
       <span class="attr">Type</span><span class="kwrd">="Text"</span> <span class="attr">Name</span><span class="kwrd">="Sample"</span> <span class="attr">StaticName</span><span class="kwrd">="Sample"</span>
       <span class="attr">ColName</span><span class="kwrd">="nvarchar11"</span> <span class="attr">DisplayName</span><span class="kwrd">="Sample"</span>
       <span class="attr">Description</span><span class="kwrd">="A Sample Field"</span> <span class="attr">Group</span><span class="kwrd">="Samples"</span>
       <span class="attr">Required</span><span class="kwrd">="FALSE"</span> <span class="attr">Hidden</span><span class="kwrd">="FALSE"</span> <span class="attr">Customization</span><span class="kwrd">=""</span>
       <span class="attr">ReadOnly</span><span class="kwrd">="TRUE"</span> <span class="attr">RowOrdinal</span><span class="kwrd">="0"</span>
       <span class="attr">Node</span><span class="kwrd">="/my:myFields/my:Sample"</span>
       <span class="attr">SourceID</span><span class="kwrd">="{A1234567-89AB-CDEF-0123-456789ABCDEF}"</span> <span class="kwrd">/&gt;</span>
</pre>
<p>Note that the Sample field is defined from a site Column with the same ID as the Field.&nbsp; The site column is defined in the feature identified by the SourceID GUID.&nbsp; Also, the Node field defines where the value is promoted from (synchronized with) in the XML document.&nbsp; For an extensive look at using XML with SharePoint lists, see Andrew May's 5-part blog on this topic: <a title="https://blogs.msdn.com/andrew_may/archive/2006/06/29/SharePointBeta2XMLDocumentParsers1.aspx" href="https://blogs.msdn.com/andrew_may/archive/2006/06/29/SharePointBeta2XMLDocumentParsers1.aspx">https://blogs.msdn.com/andrew_may/archive/2006/06/29/SharePointBeta2XMLDocumentParsers1.aspx</a>.</p>
<p>A nice feature of SharePoint is that when you define a field this way, you can update the XML file and the column value is updated, or you can update the column value and the XML file will be updated.&nbsp; Except in our case, it wasn't working correctly.&nbsp; If the XML value were updated, the column value would be updated, but not the other way around.</p>
<p>We had code that would get a value from another system and update the column in the list.&nbsp; The code would appear to work, without raising any errors, but neither the column value nor the value in XML would be updated.&nbsp; No errors were logged anywhere that we could find.</p>
<p>After going around in circles trying different ways in code for updating the value, I finally thought to check the schema file for that particular list and compare it against another site's list definition that was working.&nbsp; It turns out that the field we were trying to update had FieldRef in the &lt;ContentTypes&gt; section of the list definition.</p><pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">FieldRef</span> <span class="attr">ID</span><span class="kwrd">="{12345678-9ABC-DEF0-1234-56789ABCDEF0}"</span>
          <span class="attr">Name</span><span class="kwrd">="Sample"</span> <span class="attr">DisplayName</span><span class="kwrd">="Sample"</span>
          <span class="attr">Required</span><span class="kwrd">="FALSE"</span> <span class="attr">Hidden</span><span class="kwrd">="FALSE"</span>
          <span class="attr">Customization</span><span class="kwrd">=""</span> <span class="attr">ReadOnly</span><span class="kwrd">="TRUE"</span>
          <span class="attr">Node</span><span class="kwrd">="/my:myFields/my:Sample"</span> <span class="kwrd">/&gt;</span></pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>The other site where it was working only had a Field definition, not the FieldRef.&nbsp; After commenting out the FieldRef and creating a new list from that definition, it started working.&nbsp; I still have no explanation about why it was causing the problem, but it is working.</p>
<p>The last thing we had to do was to fix existing lists.&nbsp; I wrote some code to open the list, copy the existing values from the column, delete the field, add the field back in using the site column definition and then restore the previous values to the column.</p>]]></content:encoded>
    </item>
    <item>
      <title>Getting To the Root (Well Almost) - Navigating the SPWeb Hierarchy</title>
      <link>https://docs.microsoft.com/archive/blogs/valdon/getting-to-the-root-well-almost-navigating-the-spweb-hierarchy</link>
      <pubDate>Tue, 11 Nov 2008 17:13:36 GMT</pubDate>
      <dc:creator><![CDATA[Valdon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/valdon/2008/11/11/getting-to-the-root-well-almost-navigating-the-spweb-hierarchy/</guid>
      <description><![CDATA[Recently I was faced with the problem of finding an ancestor web (SPWeb object) of the current...]]></description>
      <content:encoded><![CDATA[<p>Recently I was faced with the problem of finding an ancestor web (SPWeb object) of the current web.&nbsp; The ancestor needed to be the one just below the RootWeb.&nbsp; I quickly put together a solution that worked, but I later realized that it had massive memory "leaks" (technically, they're not memory leaks, but they have the same effect so we'll just call them leaks).&nbsp; For more information on this common coding problem, see Roger Lamb's excellent blog entry on this topic: <a title="https://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx" href="https://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx">https://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx</a></p><font size="2"></font> <blockquote><pre class="csharpcode">SPWeb nextToTopWeb = SPContext.Current.Web;
<span class="kwrd">while</span> (nextToTopWeb.ParentWeb != <span class="kwrd">null</span> &amp;&amp; !nextToTopWeb.ParentWeb.IsRootWeb)
{
    nextToTopWeb = nextToTopWeb.ParentWeb;
}
<font color="#008000">// Code that </font><font color="#008040">uses nextToTopWeb </font></pre></blockquote>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>The problem is that the ParentWeb method returns an SPWeb object that needs to be disposed and I was calling ParentWeb multiple times without any disposing going on (and in the while expression, it wasn't even returning to a variable).&nbsp; Also, at the end I was not disposing of nextToTopWeb, which you should do if it got assigned a ParentWeb (which happened when it went at least once through the loop), but should not do if you got it through SpContext.Current (which happened if we start at the root web or one below).&nbsp; For some reason, it took me a while to wrap my brain around this little problem and I think I've come up with a solution: 
<blockquote><pre class="csharpcode">SPWeb nextToTopWeb = SPContext.Current.Site.OpenWeb(SPContext.Current.Web.ServerRelativeUrl);
<span class="kwrd">while</span> (<span class="kwrd">true</span>)
{
    SPWeb nextWeb = nextToTopWeb.ParentWeb;
    <span class="kwrd">if</span> (nextWeb == <span class="kwrd">null</span> || nextWeb.IsRootWeb)
    {
        <span class="rem">// We found the next-to-top web</span>
        nextWeb.Dispose(); <span class="rem">// Line added 1/15/08</span>
        <span class="kwrd">break</span>;
    }
    nextToTopWeb.Dispose();
    nextToTopWeb = nextWeb;
}

<span class="rem">// Code that uses nextToTopWeb </span>
nextToTopWeb.Dispose();</pre></blockquote>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>There are probably more elegant ways to do this (code purists won't like using break in an otherwise infinite while loop), but this worked for our project.&nbsp; The key here is to have an intermediary variable (in this case, nextWeb) that holds a reference to the parent web so the current one can be disposed.&nbsp; Also, this code should be put in a try...catch...finally block so if there is an error, you can still dispose of topWeb. 
<p>I'm also a bit concerned about performance since it is throwing around SPWeb objects like candy at a parade (SPWeb objects are pretty heavy and have sharp corners - not recommended for throwing at bystanders).&nbsp; There hasn't been an issue thus far, but any suggestions on improving the algorithm are welcome.</p>]]></content:encoded>
    </item>
  </channel>
</rss>