Skip navigation

Category Archives: wss

I’ve spent a few hours trying to unravel SharePoint’s rather scarcely documented schema.xml definition for custom list templates deployeed in features, specifically the <Views> element.

The task: I wanted to render a column in the view that was not based on a field, which as you know, comes from the list values (which come from the database).  In effect, I wanted to create a kind of custom-calculated column.  The “calculation” was an external link to a configurable server URL based on one of the fields in the list.

This was actually easier than I expected.  You need to locate the <View><ViewBody> portion of the schema.xml.  The weirdness comes from the <Fields> element.  As is noted in the Microsoft docs, when the parser comes through and hits the <Fields> element, it treats it as the opening of a loop that essentially says foreach(Field f in list.Fields).  You can render the field in its default manner by using the empty tag <Field/>, so for example in the default view definitions you can copy from the standard SharePoint lists, the body of the <Fields> element is little more than wrapping a <Field> element in some <td> tags to make the columns in table.

If you want to add another column to the end of the table, you are going to want to add a <td> tag after the </Fields> tag (after the loop).  But how do you display a single <Field> value outside of the <Fields> element?

The answer is, I’m pretty sure you can’t.  But what you can do is put a second <Fields> tag in the <ViewBody> tag, and you can use <FieldSwitch> to render only one field.

You do it like this:

         <Fields>
            <FieldSwitch>
              <Expr>
                <Property Select=”Name” />
              </Expr>
              <Case Value=”YourFieldName”>
                <Column/>
              </Case>
            </FieldSwitch>
          </Fields>

As you may know, each field has a collection of properties associated with it.  In the SP Object Model you would get property values by saying list.Fields[“YourFieldName”].GetProperty(“PropertyName”).  In this case, the <expr><property> combo is indicating that you want to compare a field’s “Name” property, and the <Case Value=”YourFieldName”/> means you want to render everything inside the <case> tag when the field’s Name property equals “YourFieldName”.  Pretty straightforward, right?  (By the way, <Column /> is shorthand to render the raw value of the field).

The only problem is that a field’s name according to all of SharePoint’s user interface is actually not its name – it’s its DisplayName property.  For example, the column headers you see at the top of the list are referred to as the field’s name when you modify a list’s columns in the Modify View page, but if you try to use the XML above – namely, select a field based on its Name property by matching <case Value=”YourFieldName”>, nothing will work.  In other words, if the column’s header text is “YourFieldName”, using the above xml snippet just won’t work.

Weird, huh?

In order to figure out what I was doing wrong, I had to set a breakpoint where I could probe my SharePoint list object and figure out what my field’s name was if it wasn’t “MyFieldName”.

Turns out it was “_x0036_F80E0E2_x002d_1798_x002d_”.  Of course.

There’s actually a hint in the SP Object Model API that a field’s “name” for UI purposes is actually not it’s name for API purposes.  Look at this prototype for SPFieldCollection.Add:

C#
public string Add (
    string strDisplayName,
    SPFieldType type,
    bool bRequired
)

A-ha.  A clue.  It turns out that correct property name to use is DisplayName.  We modify our schema.xml this way:

         <Fields>
            <FieldSwitch>
              <Expr>
                <Property Select=”DisplayName” />
              </Expr>
              <Case Value=”YourFieldName”>
                <Column/>
              </Case>
            </FieldSwitch>
          </Fields>

And like magic, it works like a charm.

Don’t let this one bite you – it took me a few hours of trial and error before I finally figured this one out.

Advertisements