Easily Making the Data Form Web Part reusable


There are plenty of examples out there of the many capabilities of the so called “Swiss Army” Web Part, the Data Form Web Part.  Although a lot of developers know about the capabilities, many of them dismiss this Web Part as a one-off, not a versatile re-useable Web Part.  I ran into such a situation recently on a project where one of the developers wanted to write a custom Web Part to display some data that was easily done by the Data Form Web Part.  His reason for writing a custom Web Part was because the requirement was for this Web Part to be re-usable across site collections.  The goal of this post is to show how to easily transform a one-off Data Form Web Part into a re-useable web part, with no code.  Let’s get started…

The first thing you will want to do is build your Data Form Web Part.  If you are simply accessing an external data source such as a web service then you can skip the next step.  You can see an example of using the Flickr web services here.  There are plenty more examples of how to use the Data Form Web Part over on the SharePoint Designer Team Blog.

If your data source is SharePoint content such as a list or library you will need to make sure that you update your SPDataSource to be Site Collection agnostic.  The most important part of this is removing the “ListID” paramter from the paramter list.  Here is an example of what was generated by SharePoint designer and what it looked like after I modified it.

SharePoint Designer

<WebPartPages:DataFormWebPart runat="server" IsIncluded="True" FrameType="None" NoDefaultStyle="TRUE" ViewFlag="0" Title="Important Phone Numbers" ListName="{1EC8059A-4D81-4AD9-88D2-56B47F6BDCF2}" Default="FALSE" 
DisplayName="Important Phone Numbers" __markuptype="vsattributemarkup" __WebPartId="{69639AAA-B062-42E5-9C34-11700E80E785}" id="g_69639aaa_b062_42e5_9c34_11700e80e785">
    <DataSources>
        <SharePoint:SPDataSource 
            runat="server" 
            DataSourceMode="List" 
            UseInternalName="true" 
            selectcommand="&lt;View&gt;&lt;/View&gt;" id="Important_x0020_Phone_x0020_Numbers1">
            <SelectParameters>
                <WebPartPages:DataFormParameter Name="ListID" ParameterKey="ListID" PropertyName="ParameterValues" DefaultValue="1EC8059A-4D81-4AD9-88D2-56B47F6BDCF2"/>
            </SelectParameters>
            <DeleteParameters>
                <WebPartPages:DataFormParameter Name="ListID" ParameterKey="ListID" PropertyName="ParameterValues" DefaultValue="1EC8059A-4D81-4AD9-88D2-56B47F6BDCF2"/>
            </DeleteParameters>
            <UpdateParameters>
                <WebPartPages:DataFormParameter Name="ListID" ParameterKey="ListID" PropertyName="ParameterValues" DefaultValue="1EC8059A-4D81-4AD9-88D2-56B47F6BDCF2"/>
            </UpdateParameters>
            <InsertParameters>
                <WebPartPages:DataFormParameter Name="ListID" ParameterKey="ListID" PropertyName="ParameterValues" DefaultValue="1EC8059A-4D81-4AD9-88D2-56B47F6BDCF2"/>
            </InsertParameters>
        </SharePoint:SPDataSource>
    </DataSources>

After Modifications

<WebPartPages:DataFormWebPart runat="server" IsIncluded="True" FrameType="None" NoDefaultStyle="TRUE" ViewFlag="0" Title="Important Phone Numbers" ListName="{1EC8059A-4D81-4AD9-88D2-56B47F6BDCF2}" Default="FALSE" 
DisplayName="Important Phone Numbers" __markuptype="vsattributemarkup" __WebPartId="{69639AAA-B062-42E5-9C34-11700E80E785}" id="g_69639aaa_b062_42e5_9c34_11700e80e785">
    <DataSources>
        <SharePoint:SPDataSource 
            runat="server" 
            DataSourceMode="List" 
            UseInternalName="true" 
            selectcommand="&lt;View&gt;&lt;/View&gt;" id="Important_x0020_Phone_x0020_Numbers1">
            <SelectParameters>
                <WebPartPages:DataFormParameter Name="ListName" ParameterKey="ListName" PropertyName="ParameterValues" DefaultValue="Important Phone Numbers" />
                <asp:Parameter runat="server" Name="WebUrl" DefaultValue="{sitecollectionroot}"/>
                <asp:Parameter Name="MaximumRows" DefaultValue="2"/>
            </SelectParameters>
        </SharePoint:SPDataSource>
    </DataSources>
    
Since we are just displaying data I removed the Insert, Update, and Delete parameter collections.  The important modification I made to the "SelectParameters" parameter collection was to change the "ListID" parameter to "ListName".  
This will get the list by name instead of GUID, which is important if you are going to reuse this Web Part in another Site Collection.  At this point you can continue updating your DFWP by modifying the XSL or adding some parameters from the querystring
or other controls on the page, there are plenty examples out there of how to do this, I won't go into detail here.
 
Next we need to create a reusable web part out of this DFWP.  To do this we will place the DFWP in a Web Part Zone and export through the standard SharePoint browser interface.
Here is an example of my markup:
<WebPartPages:WebPartZone 
    runat="server" 
    AllowPersonalization="false" 
    ID="TopZone" 
    Title="Top Zone" 
    Orientation="Horizontal">
<ZoneTemplate>

<WebPartPages:DataFormWebPart runat="server" IsIncluded="True" FrameType="None" NoDefaultStyle="TRUE" ViewFlag="0" Title="Important Phone Numbers" ListName="{1EC8059A-4D81-4AD9-88D2-56B47F6BDCF2}" Default="FALSE" DisplayName="Important Phone Numbers" __markuptype="vsattributemarkup" __WebPartId="{69639AAA-B062-42E5-9C34-11700E80E785}" id="g_69639aaa_b062_42e5_9c34_11700e80e785" partorder="1">

....[omitted for brevity]

</WebPartPages:DataFormWebPart>

</ZoneTemplate>
</WebPartPages:WebPartZone>
 
Now when I go to my page I can edit the page, and select export.  
image 
This will produce a .webpart file that I can then package in my features or use in other web part galleries to create an easily reusable DFWP.
 
 
 

Comments (11)

  1. Reggie says:

    I don’t understand how this is Site Collection agnostic because you still have the Guid of the List in the web part properties.

    It’s just not apparent because of the styling of your webpage but ListName="{1EC8059A-4D81-4AD9-88D2-56B47F6BDCF2}" still exists in there.

  2. Roy Higgs says:

    Also, if you need to filter the web part then the ListName parameter is required and unfortunately the ListName parameter (at the DataFormWebPart level) is the GUID of the list and not the actual list name. So, at this point, I can’t find a way to get a reusable DFWP if I need to filter it.

  3. Sean Walker says:

    Greetings,

    I am a somewhat Sharepoint noobie, and have been hunting and experimenting for the last 2 days on how to do this reliably.  After playing around with this method for some time I found what seems to be a very simple and reliable solution – with one caveat.

    In the DFWP, in the <ParameterBindings> section, there is a line:

    <ParameterBinding Name="ListID" Location="None" DefaultValue="01434AE1-3FE1-4458-9F8F-1CE902FBBE04"/>

    By simply changing the above to:

    <ParameterBinding Name="ListID" Location="CAMLVariable" DefaultValue="CurrentListID"/>

    It will pull the ListID from the current context.  I have had sucess in creating a page in SPD, getting it working the way I want on a specific list – then changing the above line and ‘save as’ to the other list where I want to reuse this DFWP.

    I found this here:  http://dattard.blogspot.com/2007/05/sharepoint-2007-solving-list-guid.html

    Hope this helps someone.

  4. Since my post on Easily Making the DataFormWebPart Reuseable , I’ve had a couple questions on the parameters

  5. Manuel says:

    Thanks.  Exactly the tweak I needed.  I knew it had to be there… but it’s nice when someone else busts their noodle for you 🙂

  6. Perry says:

    Some of the critical code is not shown; it appears to be cutoff to the right. 🙁

  7. Really interesting post. I realise this is a relatively old post but…

    I have a web part that I'd like to dynamically change the <Order By> part of my selectcommand based on the querystring of the page's URL.  

    If my querystring variable, say 'X', equals 1, I want the sort order to be ColumnX, ColumnY. If X equals some other value, I want the sort order to be just ColumnY.

    1. Is it possible to parameterise the entire <Order By>, so <OrderBy><FieldRef Name="ColumnX" Ascending="TRUE"/><FieldRef Name="ColumnY" Ascending="TRUE"/></OrderBy> can be parameterised as, say, {myOrderBy} ?

    2. Is it possible to conditionally test the querystring and to determine what to store in the parameter

    ..or perhaps there's an alternative way to solve my problem.

  8. Perry says:

    The blog post is badly cut-off to the right, sot that both code and text are missing.

  9. DataFormWebPart Connections Don't Work in Web Part Pages says:

    … when created and edited in the browser, rather than in SPD (at least with SP 2010).  I am trying to make reusable connectable DFWPs which use a web service data source.

    So does anyone know how to do this???

  10. Thomas Daly says:

    I see you are using <asp:Parameter runat="server" Name="WebUrl" DefaultValue="{sitecollectionroot}" />

    where is there more information on what tokens work here ? I've never seen sitecollectionroot used anywhere else