mo.notono.us

Monday, March 30, 2009

Beware of SPList.Items.Add()

What could possibly be wrong with this statement?

SPListItem myItem = myList.Items.Add();

This is what’s wrong with it – this is the innards of SPList.Items:

public virtual SPListItemCollection Items
{
    get
    {
        SPQuery query = new SPQuery();
        query.ViewAttributes = "Scope=\"Recursive\"";
        return this.GetItems(query);
    }
}

That’s right, the entire collection, every single item, item is returned and then Add() is applied to the final SPListItemCollection instance, which results in an internal SPListItem constructor call:

public SPListItem Add(string folderUrl, 
    SPFileSystemObjectType underlyingObjectType, string leafName)
{
  return new SPListItem(this, folderUrl, underlyingObjectType, leafName);
}
internal SPListItem(SPListItemCollection items, string folderUrl, SPFileSystemObjectType underlyingObjectType, string leafName)
{
    this.m_ItemGuid = Guid.Empty;
    this.m_fsoType = SPFileSystemObjectType.Invalid;
    if (underlyingObjectType != SPFileSystemObjectType.File)
    {
        while (underlyingObjectType != SPFileSystemObjectType.Folder)
        {
            throw new ArgumentOutOfRangeException("underlyingObjectType");
        }
    }
    this.m_Items = items;
    this.m_uiItemsUpdateVersion = items.UpdateVersion;
    this.m_iIndex = -1;
    this.m_strNewFolderName = folderUrl;
    this.m_fsoType = underlyingObjectType;
    this.m_strNewBaseName = leafName;
    this.m_bNewItem = true;
}

So what should be used instead?  Rob Garrett suggests creating a new empty SPListItemCollection and adding to it, below is his method converted to an Extension method (and renamed to be more easily found):

public static SPListItem AddItemOptimized(this SPList list)
{
  const string EmptyQuery = "0";
  SPQuery q = new SPQuery {Query = EmptyQuery};
  return list.GetItems(q).Add();
}

 

(and no, neither Rob nor I have instrumented the difference between these two methods, but Reflector doesn’t lie…)

Labels: , , , , ,

Friday, March 27, 2009

Google Docs Gets Drawings

So will this become the new de-facto wire framing tool too?


Nah - too simple.  More like online MS Paint (with snap to grid, and every shape a layer)



Update: Not to mention that the Drawing links are broken when you export the doc as a blog post.

Labels: , ,

Wednesday, March 11, 2009

ASP.NET 101 Reminder 2: ListItem[] is an array of Reference Types

..which means that if you fill one ListControl with the ListItem[] array, and then fill another ListControl with the same array, BOTH DropDownLists will be updated if you modify any ListItem (such as selecting it: ListItem.Selected = true;)

If you think of a ListControl as its HTML equivalent then this may be a bit confusing and bug-prone (and indeed, once rendered as HTML the controls are no longer in sync, it only happens server-side), but from an OO perspective it does make perfect sense.

It just makes me wish for easier and generic deep cloning of collections of objects…. Sigh.

Labels: , , , , , ,

ASP.NET 101 Reminder: ListControl.Text == ListControl.SelectedValue…

…and NOT ListControl.SelectedItem.Text

ListControl implements IEditableTextControl and thus ITextControl, which mandates the Text property.  For whatever reason (I’m sure it was a good one) the ASP.NET architects chose to make the Text property implementation get and set the ListControl.SelectedValue rather than ListControl.SelectedItem.Text.

 

Coincidentally, there is no ListControl.FindByText method: the following extension methods may come in handy:

/// <summary>
/// Performs a case insensitive comparison finding a ListItem by its text value, and selecting that item
/// </summary>
/// <param name="listControl">The list control</param>
/// <param name="text">The text to match</param>
/// <returns>The first matched, selected <see cref="SPListItem"/> or null if not found.</returns>
public static ListItem SelectFirstByText(this ListControl listControl, string text)
{
  // first clear any previous selection 
  listControl.SelectedIndex = -1;
		
  foreach (ListItem item in listControl.Items)
  {
    if (string.Equals(item.Text, text, System.StringComparison.OrdinalIgnoreCase))
    {
      item.Selected = true;
      return item;
    }
  }
  //if not found...
  return null;
}

/// <summary>
/// Performs a case insensitive comparison finding ListItems by their text value, and selecting those items
/// </summary>
/// <param name="listControl">The list control.</param>
/// <param name="text">The text to match.</param>
/// <returns>An integer array of matched indices.</returns>
public static int[] SelectByText(this ListControl listControl, string text)
{
  List matches = new List();
  // first clear any previous selection 
  listControl.SelectedIndex = -1;
  int i = 0;
  foreach (ListItem item in listControl.Items)
  {
    if (string.Equals(item.Text, text, System.StringComparison.OrdinalIgnoreCase))
    {
      item.Selected = true;
      matches.Add(i);
    }
    i++;
  }
  return matches.ToArray();
}

Labels: , , , , ,

Tuesday, March 10, 2009

Flying Nuts

My neighbor, Sean Tepper (graphics designer extraordinaire, designer of the squrl.us logo) forwarded the video below, shot not too far from where I grew up in Norway:


wingsuit base jumping from Ali on Vimeo.

Insane. Any one little gust of wind and they'd all be candidates for the Darwin Awards.

Labels: , , , ,

Visual Studio: A handful of useful Find and Replace Expressions

  • Find empty get; set; property declarations:
    \n:b*\{:b*\n:b*get;:b*\n:b*set;:b*\n:b*\}
  • Replace empty get; set; declarations with single line equivalent:
    { get; set; }
  • Find candidates for single line summary comments:
    /// \<summary\>\n:b+///:b*{[^\n]*}:b*\n:b+/// \</summary\>
  • Replace candidates with single line equivalent:
    /// \<summary\>\1\</summary\>
  • Find Class Diagram generated get:
    get\n:b+\{\n:b+throw new System.NotImplementedException\(\);\n:b+\}
  • Find Class Diagram generated empty set:
    set\n:b+\{\n:b+\}

Labels: , , , , ,

Friday, March 06, 2009

SharePoint 14 Wishlist

While 14 may not be coming down the pike until next year, the Alpha bits are in controlled distribution, and while I haven’t actually seen them yet, I have hopes for some major changes. 

Rather than posting my wishlist here, I thought I’d create one on Google Moderator…

See http://moderator.appspot.com/#16/e=295af – go nuts!

Labels: , , , , ,