<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Beth Massi - Sharing the goodness that is VB : ADO.NET Data Services</title><link>http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx</link><description>Tags: ADO.NET Data Services</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Interop Between VBA and Visual Studio Office Solutions (VSTO)</title><link>http://blogs.msdn.com/bethmassi/archive/2009/11/05/interop-between-vba-and-visual-studio-office-solutions-vsto.aspx</link><pubDate>Fri, 06 Nov 2009 05:03:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9918383</guid><dc:creator>Beth Massi</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9918383.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9918383</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9918383</wfw:comment><description>&lt;p&gt;Couple weeks ago when &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/10/20/sdc-2009-recap-surprise.aspx" target="_blank"&gt;I was in Holland speaking at SDC&lt;/a&gt; an attendee asked me how he could call methods in an Office solution (VSTO) from VBA functions defined in a document and vice versa. I thought I’d follow up with a post on how to do this, but first a little background on why this architecture would make sense. &lt;/p&gt;  &lt;p&gt;There are many reasons why you would build an Office solution using Visual Studio (VSTO) as opposed to a pure VBA solution. &lt;a href="http://geeks.netindonesia.net/blogs/andriyadi/default.aspx"&gt;Andri Yadi&lt;/a&gt;, VSTO MVP, &lt;a href="http://geeks.netindonesia.net/blogs/andriyadi/archive/2008/08/20/vba-vs-vsto.aspx" target="_blank"&gt;wrote a great piece on his blog a while back explaining the benefits of VSTO compared to VBA&lt;/a&gt;. He broke it down into 10 areas, of which the main benefits are the tools and designers you have available in Visual Studio as well as the entire .NET framework and modern languages at your disposal. &lt;/p&gt;  &lt;p&gt;However, there are probably many VBA assets that people in your company have already written, like complex algorithms or other business logic that you really don’t want to rewrite. Or maybe you still want to allow users to customize these functions in the VBA editor but it’s necessary for you to call them from your .NET code. &lt;/p&gt;  &lt;p&gt;Likewise, you may want to develop a customization that takes advantage of WCF services or a WPF UI, modern language features, or any other feature of the .NET framework that would be difficult or impossible to do in VBA, and you want the user to be able to access these methods from their VBA functions. The attendee at SDC didn’t go into much detail on what his Office customization was doing exactly but he wanted to make some of his public methods available to his VBA users and this makes sense in a lot of situations. Luckily Visual Studio makes this very easy to do. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Creating an Excel Document Customization&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;For this example I’ll create an Excel document customization that accesses data through a WCF service and does some calculations on that data. The calculations, however, will be in VBA. To access the remote data over the internet I’ll create an ADO.NET Data Service. I want to pull up data in a Northwind view called &lt;em&gt;Sales Totals By Amount&lt;/em&gt;. I’ve shown how to create an ADO.NET Data Service many times before so I won’t go into too much detail here. Please refer to the steps shown in the &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target="_blank"&gt;Using ADO.NET Data Services&lt;/a&gt; article. The only difference in this case is I selected the View &lt;em&gt;Sales Totals By Amount&lt;/em&gt; into my Entity Framework model when I performed that step. &lt;/p&gt;  &lt;p&gt;I have an Excel macro-enabled workbook that already has a simple VBA function that Sums all the columns below the first row. The function is sitting in a module called MyFunctions. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_2.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_thumb.png" width="669" height="251" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;To create the new&amp;#160; Excel workbook customization I’m going to add a new project to my solution and select Office 2007 Excel Workbook. Next it will ask if you want to create a new document or use an existing one, here’s where I’ll specify the macro-enabled workbook I already have above.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_6.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_thumb_2.png" width="613" height="446" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Next Add a Service Reference to the ADO.NET Data Service (which I called NorthwindReportService) &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target="_blank"&gt;just like I showed here&lt;/a&gt; and copy the URI into your clipboard. Then create a setting to store the URI, just double-click on My Project (Properties in C#) and select the Settings tab and enter an application scope property called ServiceURI.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_8.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_thumb_3.png" width="684" height="115" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When you add the service reference this generates client-side proxy types that you can use. I’m going to bind the data returned from Sales_Totals_by_Amount to an Excel ListObject. Open the Data Source window (Data –&amp;gt; Show Data Sources) and then add a new data source (Data –&amp;gt; Add New Data Source…). In the Data Source Connection Wizard select Object, then Next, then expand the types in your project’s NorthwindReportService namespace. Select Sales_Totals_by_Amount and then click Finish and you will see the type’s properties appear in the Data Sources Window:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_10.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_thumb_4.png" width="670" height="515" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Double-click on Sheet1 in the project and drag the Sales_Totals_by_Amount from the Data Sources window onto the &lt;strong&gt;second &lt;/strong&gt;row of the sheet (our macro is going to sum into the first row so we want to place the data starting on the second row). This will automatically set up a BindingSource in the system tray that we will use to set our list of data coming from the service. If you are familiar with Winforms development this should seem very familiar. The ListObject is the main data object you work with in Excel solutions. For this example I’m going to select the OrderId column, right-click and then Delete. I’ll do the same to the ShippedDate column because I only want to display the CompanyName and SaleAmount for this example. Finally I’ll set the formatting (Home Tab on the Excel Designer) to Currency for the first cell. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_12.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_thumb_5.png" width="589" height="373" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now we’re ready to write some code to load our data. Right-click on ThisWorkbook and select View Code. Here I’m going to create a Friend ReadOnly Property so we can easily access the service reference from anywhere in the project. I’m making this Friend so that it won’t be visible outside of the .NET assembly. I’m also creating a Public method that gets the data from our service and optionally accepts a Company Name. The results are then set to the DataSource of the ListObject’s BindingSource on Sheet1:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;VBATest.NorthwindReportService

&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;ThisWorkbook

    &lt;span style="color: blue"&gt;Private &lt;/span&gt;_ReportService &lt;span style="color: blue"&gt;As New &lt;/span&gt;NorthwindEntities(&lt;span style="color: blue"&gt;New &lt;/span&gt;Uri(&lt;span style="color: blue"&gt;My&lt;/span&gt;.Settings.ServiceURI))
    &lt;span style="color: blue"&gt;Friend ReadOnly Property &lt;/span&gt;ReportService() &lt;span style="color: blue"&gt;As &lt;/span&gt;NorthwindEntities
        &lt;span style="color: blue"&gt;Get
            Return &lt;/span&gt;_ReportService
        &lt;span style="color: blue"&gt;End Get
    End Property

    Public Sub &lt;/span&gt;GetData(&lt;span style="color: blue"&gt;Optional ByVal &lt;/span&gt;companyName = &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;Try
            If &lt;/span&gt;Globals.Sheet1 &lt;span style="color: blue"&gt;IsNot Nothing Then

                Dim &lt;/span&gt;results &lt;span style="color: blue"&gt;As &lt;/span&gt;IEnumerable(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Sales_Totals_by_Amount)

                &lt;span style="color: blue"&gt;If &lt;/span&gt;companyName = &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;Then
                    &lt;/span&gt;results = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.ReportService.Sales_Totals_by_Amount
                &lt;span style="color: blue"&gt;Else
                    &lt;/span&gt;results = &lt;span style="color: blue"&gt;From &lt;/span&gt;s &lt;span style="color: blue"&gt;In Me&lt;/span&gt;.ReportService.Sales_Totals_by_Amount _
                              &lt;span style="color: blue"&gt;Where &lt;/span&gt;s.CompanyName.StartsWith(companyName)
                &lt;span style="color: blue"&gt;End If

                &lt;/span&gt;Globals.Sheet1.Sales_Totals_by_AmountBindingSource.DataSource = results.ToList()
            &lt;span style="color: blue"&gt;End If
        Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            &lt;span style="color: green"&gt;'TODO: Error Handling
            &lt;/span&gt;MsgBox(ex.ToString())
        &lt;span style="color: blue"&gt;End Try
    End Sub

    Private Sub &lt;/span&gt;ThisWorkbook_Startup() &lt;span style="color: blue"&gt;Handles Me&lt;/span&gt;.Startup

    &lt;span style="color: blue"&gt;End Sub

    Private Sub &lt;/span&gt;ThisWorkbook_Shutdown() &lt;span style="color: blue"&gt;Handles Me&lt;/span&gt;.Shutdown

    &lt;span style="color: blue"&gt;End Sub

End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Calling VBA from VSTO&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next I want to create a button on the ribbon that will first call the GetData method, then select the first cell in Sheet1, and finally call the VBA function SumBelow. In order to call a VBA method from VSTO you call Globals.ThisWorkbook.Application.Run passing it the&lt;strong&gt; full name&lt;/strong&gt; to the VBA method. For this example that would be VBATest.xlsm!MyFunctions.SumBelow. &lt;/p&gt;

&lt;p&gt;Add a New Item to the project and select Office, Ribbon (Visual Designer) and then drag a Button from the Office Ribbon Controls to the Group and Label it “Get Data”. I also specified an OfficeImageId to make it look pretty. (BTW, a nice way to browse the Office Images is to &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=46B6BF86-E35D-4870-B214-4D7B72B02BF9&amp;amp;displaylang=en" target="_blank"&gt;install the VSTO Power Tools&lt;/a&gt; and install the RibbonID Add-in like &lt;a href="http://msdn.microsoft.com/en-us/vsto/dd229920.aspx" target="_blank"&gt;Ty shows in this video&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_14.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_thumb_6.png" width="675" height="400" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Double-click on the Get Data button to add a click event handler and we’ll write the following code to load all the data and then call the VBA function. You need to make sure you set up proper error handling here because if the VBA function is removed or renamed the code here will fail. This code will also fail if the appropriate access is not granted to VBA macros in Excel. By default, VBA macros are not enabled but you can enable them on a per workbook basis (there’s a button at the top of the first sheet when you run it). This scenario assumes you have existing VBA code that has permission to run and you’re now calling those existing functions from VSTO.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;VBATest.NorthwindReportService
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;Microsoft.Office.Tools.Ribbon

&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Ribbon1

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;Button1_Click() &lt;span style="color: blue"&gt;Handles &lt;/span&gt;Button1.Click
        &lt;span style="color: green"&gt;'load the data from the service
        &lt;/span&gt;Globals.ThisWorkbook.GetData()
        &lt;span style="color: blue"&gt;Try
            &lt;/span&gt;&lt;span style="color: green"&gt;'Make sure the first cell is selected
            &lt;/span&gt;Globals.Sheet1.Range(&lt;span style="color: #a31515"&gt;&amp;quot;A1&amp;quot;&lt;/span&gt;).Select()
            &lt;span style="color: green"&gt;'Run the VBA function. This will result in a runtime error if the function 
            ' is removed or renamed or not allowed to run so make sure to provide &lt;br /&gt;            ' adequate error handling.             
            &lt;/span&gt;Globals.ThisWorkbook.Application.Run(&lt;span style="color: #a31515"&gt;&amp;quot;VBATest.xlsm!MyFunctions.SumBelow&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            &lt;span style="color: green"&gt;'Todo: Error handling
            &lt;/span&gt;MsgBox(ex.ToString())
        &lt;span style="color: blue"&gt;End Try
    End Sub
End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Hit F5 to run. If you see a Security Warning (the default) that Macros are disabled, then just click Options and select “Enable this content”. Select the Add-Ins tab on the Ribbon and click the GetData button to see the data get loaded from the service and then the SumBelow VBA function will be called which will auto-sum the SaleAmount field and show the total in the first row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calling VSTO methods from VBA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As you can see it’s really easy to call VBA code from your Office solution in Visual Studio (VSTO) but it’s also fragile because of the late-bound architecture and the requirement that macros be enabled for the Workbook. Like all late-bound code, you need to have adequate error handling to prevent crashes. Much less fragile is calling VSTO methods from VBA functions because these methods are compiled into your .NET assembly and exposed via COM-interop which makes them available to VBA. &lt;/p&gt;

&lt;p&gt;If we go back to our project and double-click on ThisWorkbook and look in the Properties window, you should see a property called EnableVbaCallers. Setting that Property to True will expose all Public methods in the ThisWorkbook class via COM to VBA. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_16.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_thumb_7.png" width="325" height="196" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you now go back into the code-behind for ThisWorkbook you will see some COM attributes added to the class:&lt;/p&gt;

&lt;pre class="code"&gt;&amp;lt;Microsoft.VisualBasic.ComClassAttribute()&amp;gt; _
&amp;lt;System.Runtime.InteropServices.ComVisibleAttribute(&lt;span style="color: blue"&gt;True&lt;/span&gt;)&amp;gt; _
&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;ThisWorkbook&lt;br /&gt;...&lt;/pre&gt;

&lt;p&gt;Now we can call the GetData method from VBA code. Hit F5 to run and enable the macros (if asked) on the Workbook again. Select the Developer tab and launch the Visual Basic editor. (If you don’t see a developer tab click the Office icon – the globe in the left-hand corner – select Excel Options, and then on the Popular tab check the “Show Developer tab in the Ribbon”.) &lt;/p&gt;

&lt;p&gt;Double-click on the ThisWorkbook and you will see that Visual Studio added a property to our VBA code for us called CallVSTOAssembly. This allows us to call any public method we defined in the ThisWorkbook class back in Visual Studio. Let’s add another function to the MyFunctions module that collects input from the user on the company name to look up and then fetches the data by calling the GetData method in .NET.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_20.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_thumb_9.png" width="686" height="392" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Save your code here and close the VBA Editor. Now back on the Developer tab on the Ribbon select Macros and then you should see the one we just wrote called GetDataAndSumBelow, select it and click Run. It will prompt for a company name (just type ‘S’ for instance) and it will run the ADO.NET Data Service query via the call to the .NET GetData method and then will return and call the SumBelow VBA function. Cool! &lt;/p&gt;

&lt;p&gt;BUT WAIT… DON’T CLOSE EXCEL YET! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tips Editing VBA Code when Debugging&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because we wrote the second VBA function above while we were in debug mode in Visual Studio once we close Excel we will lose all the VBA code we wrote when we debug again. &lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_22.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; margin: 5px 10px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/InteroptoVBAFunctionsFromYourVisualStudi_A978/image_thumb_10.png" width="284" height="360" /&gt;&lt;/a&gt;Because of the way Visual Studio works with Office solutions, we aren’t actually editing the xlsm file in the project, we’re editing the running xlsm file in the \bin directory that has the VSTO solution attached. You &lt;strong&gt;cannot &lt;/strong&gt;just copy this one in the \bin folder back into the project otherwise Visual Studio will report an error that a customization is already attached to the document when you compile again. So what do we do?&lt;/p&gt;

&lt;p&gt;There’s probably other ways to do this but what I found the easiest was to open the Visual Basic editor again, select the MyFunctions module where all my code is stored and then right-click and select “Export File”. This will allow you to save the code outside the Workbook. Then when you debug again you can just import it by right-clicking again (delete the current one first). &lt;/p&gt;

&lt;p&gt;When you’re finally satisfied with your VBA – VSTO code interop, close Visual Studio and open the .xlsm file in the &lt;strong&gt;project directory&lt;/strong&gt; (not the \bin) and re-import your code again into that version. Then restart Visual Studio and it will be in there when you start debugging again. I find this easier than copying my code into the clipboard, closing VS, modifying the document, reopening VS every time. Just be aware of what version of the document you’re modifying when you tweak your VBA code and you should be OK.&lt;/p&gt;

&lt;p&gt;I’ve uploaded the code for this example onto Code Gallery so have a look: &lt;a title="http://code.msdn.microsoft.com/VBAVSTOInterop" href="http://code.msdn.microsoft.com/VBAVSTOInterop"&gt;http://code.msdn.microsoft.com/VBAVSTOInterop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For more information on VBA – VSTO interop with Visual Studio please check out the following resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/magazine/cc163373.aspx" target="_blank"&gt;MSDN Magazine: Extend Your VBA Code With VSTO&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb931201.aspx" target="_blank"&gt;MSDN Article: VBA Interoperability with Visual Studio Tools for the Office System (3.0)&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb814696.aspx" target="_blank"&gt;Visual How To: Interoperability Between VBA and Visual Studio Tools for the Office System (3.0)&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vsto/cc178910.aspx" target="_blank"&gt;How Do I: Call VSTO Code from VBA?&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vsto/cc748594.aspx"&gt;How Do I: Enable an Office Application Add-In using a VSTO Add-in?&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9918383" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Visual+Basic/default.aspx">Visual Basic</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Office/default.aspx">Office</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VBA/default.aspx">VBA</category></item><item><title>Using the ReportViewer with ADO.NET Data Services and Entity Framework</title><link>http://blogs.msdn.com/bethmassi/archive/2009/08/19/using-the-reportviewer-with-ado-net-data-services-and-entity-framework.aspx</link><pubDate>Thu, 20 Aug 2009 07:57:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9876342</guid><dc:creator>Beth Massi</dc:creator><slash:comments>13</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9876342.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9876342</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9876342</wfw:comment><description>&lt;p&gt;The &lt;a href="http://msdn.microsoft.com/en-us/library/ms251671.aspx" target="_blank"&gt;Winforms ReportViewer&lt;/a&gt; in Visual Studio Pro will allow you define client reports with a variety of data sources. If you’re not familiar with creating client-side reports using the ReportViewer, take a look at these videos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/ee309360.aspx" target="_blank"&gt;How Do I: Create a report from a database?&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/dd638039.aspx" target="_blank"&gt;How Do I: Create a report from a business object?&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;(The ReportViewer can also display server-based reports a la SQL Reporting Services and has a whole boatload of features that I’m not going to talk about here. For more information on this freely redistributable control, please read &lt;a href="http://msdn.microsoft.com/en-us/library/ms251671.aspx" target="_blank"&gt;ReportViewer Controls (Visual Studio)&lt;/a&gt; in the MSDN library.)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/data/bb931106.aspx" target="_blank"&gt;ADO.NET Data Services&lt;/a&gt; was released with &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=FBEE1648-7106-44A7-9649-6D9F6D58056E&amp;amp;displaylang=en" target="_blank"&gt;Visual Studio 2008 SP1&lt;/a&gt; and is basically a framework for exposing your data models via RESTful web services. So if you are building a remote CRUD data access layer then this is a technology that will make that super-simple, especially if you just want to expose a few data entities as read-only report sources. (I’ve written a lot about how to use ADO.NET Data Services in a variety of ways &lt;a href="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/Article/default.aspx" target="_blank"&gt;so check out these posts if you’re interested&lt;/a&gt;.) Entity Framework was released at the same time and you can use EF as the data model behind your ADO.NET Data Service and expose it easily. If you’ve never created one before, &lt;a href="http://msdn.microsoft.com/en-us/library/cc668796.aspx" target="_blank"&gt;check out this quick start here&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;What’s the Problem?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you’ve ever tried to use the ReportViewer to design a client-side report with an &lt;a href="http://msdn.microsoft.com/en-us/data/bb931106.aspx" target="_blank"&gt;ADO.NET Data Service&lt;/a&gt; data source (or use an &lt;a href="http://msdn.microsoft.com/en-us/library/bb738482.aspx" target="_blank"&gt;Entity Data Model&lt;/a&gt; directly) you may be disappointed. If you try to design a new report, the wizard may crash Visual Studio when selecting an entity. Yikes! &lt;/p&gt;  &lt;p&gt;Let me show you what I mean, but don’t try this at home. I have an ADO.NET Data Service based on the Northwind database &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target="_blank"&gt;&lt;strong&gt;like the one I created here&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;#160;&lt;/strong&gt;and &lt;a href="http://msdn.microsoft.com/en-us/library/cc668796.aspx" target="_blank"&gt;in the quick start&lt;/a&gt;. I then added a Windows Forms client project to the same solution (File –&amp;gt; Add –&amp;gt; New Project, then select Windows Forms App). Now open Form1 in the client and from the toolbox under the Reporting tab, drop the Microsoft ReportViewer control onto the form and from the smart tag select “Design a New Report”. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_2.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="176" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_thumb.png" width="429" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This will open the Report Wizard. The first thing I need to do is tell it what data source to use, so I’ll select Service and click Next. This will open the Add Service Reference dialog box where I can &lt;a href="http://msdn.microsoft.com/en-us/library/cc668183.aspx" target="_blank"&gt;add the reference to my data service&lt;/a&gt; and Visual Studio will generate the proxy objects for me. In this example my service is in the same solution as the client so I can just click the Discover button and Visual Studio will see it. I named it NorthwindService. Click OK then click Finish. &lt;/p&gt;  &lt;p&gt;At this point I’m brought back to the Report Wizard:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_8.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; margin: 0px 15px 0px 0px; border-left: 0px; border-bottom: 0px" height="392" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_thumb_3.png" width="433" align="left" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Hmmmm…. I’m a little lost at this point because -- didn’t I just select the data source? Why don’t I see it?&lt;/p&gt;  &lt;p&gt;Maybe I should have added the service reference first from the Solution Explorer instead of through the Report Wizard? You can do that and you’ll get to the same screen at this point.&lt;/p&gt;  &lt;p&gt;So okay, I’ll click the Add Data Source button that’s calling to me. Granted, I like clicking buttons that have the ellipsis (…) on them because I’m always curious to see what’s under them, but this seems redundant.&lt;/p&gt;  &lt;p&gt;This opens the same dialog as before but this time I’ll choose Object instead of Service. I’m choosing object this time because I’m going to try and bind to the client proxy types that were generated for me when I added the service reference. After selecting Object, click Next and expand the service namespace.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_12.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; margin: 0px 10px 0px 0px; border-left: 0px; border-bottom: 0px" height="334" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_thumb_5.png" width="434" align="left" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;For this report I want to just display a list of Customers in the system so I’ll select Customers and then click Next. &lt;/p&gt;  &lt;p&gt;Then… then…… are you ready?… you better sit down for this…. click Finish……. wait for it…. wait for it….. not responding…. uh ohhhh….. &lt;/p&gt;  &lt;p&gt;Visual Studio has encountered a problem and needs to close. Darn!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_14.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="134" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_thumb_6.png" width="247" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now that was fun. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;How Do I Fix this?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Unfortunately the Report Wizard in Visual Studio 2008 doesn’t know how to work with many-to-many relationships and that’s exactly what we have defined in our EF Entity Data Model which is what is backing our ADO.NET Data Service. Customers have many CustomerDemographics and vice versa in Northwind. You can actually define a couple classes yourself manually and create a many-to-many association between them:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Class1

    &lt;span style="color: blue"&gt;Private &lt;/span&gt;_class2 &lt;span style="color: blue"&gt;As &lt;/span&gt;List(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Class2)
    &lt;span style="color: blue"&gt;Public ReadOnly Property &lt;/span&gt;Class2() &lt;span style="color: blue"&gt;As &lt;/span&gt;List(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Class2)
        &lt;span style="color: blue"&gt;Get
            Return &lt;/span&gt;_class2
        &lt;span style="color: blue"&gt;End Get
    End Property

End Class

Public Class &lt;/span&gt;Class2

    &lt;span style="color: blue"&gt;Private &lt;/span&gt;_class1 &lt;span style="color: blue"&gt;As &lt;/span&gt;List(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Class1)
    &lt;span style="color: blue"&gt;Public ReadOnly Property &lt;/span&gt;Class1() &lt;span style="color: blue"&gt;As &lt;/span&gt;List(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Class1)
        &lt;span style="color: blue"&gt;Get
            Return &lt;/span&gt;_class1
        &lt;span style="color: blue"&gt;End Get
    End Property

End Class&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Try to use either class above as the data source of the report and it will crash too. Woah! So when the report designer tries to read these associations I’m guessing it gets into an infinite loop walking the association references back and forth and then it crashes. So it’s not an error with the generated proxy objects per se, the root cause is our object model. If I would have chosen Categories instead, it would have worked. &lt;/p&gt;

&lt;p&gt;So what do we do? We could create another layer of classes without the associations on both sides if we wanted and then use those types instead but then we’d have to write code that IMO is pretty useless, just to shape the data again how we want on the client. &lt;/p&gt;

&lt;p&gt;My recommendation is to create a separate data model for your reports that doesn’t have many-to-many associations at all. You’re going to end up with a lot of different looking entities anyways for your reports because they will most likely pull from multiple database Views and/or stored procedures. You’ll always be displaying one side of the many-to-many relationship on paper anyways. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a Reporting Data Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So let’s go back to the data service project and add a new Entity Data Model to the web project called NorthwindReport. This time I’ll just select the Customers, Orders and Order Details and all the Views defined in the database. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_16.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="434" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_thumb_7.png" width="449" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Next I’ll add the ADO.NET Data Service and call it NorthwindReport and configure it so that we’re only allowing read-only access to our data by setting the entity access rule like so:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Data.Services
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Linq
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.ServiceModel.Web

&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;NorthwindReport
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;DataService(&lt;span style="color: blue"&gt;Of &lt;/span&gt;NorthwindReportEntities)

    &lt;span style="color: blue"&gt;Public Shared Sub &lt;/span&gt;InitializeService(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;config &lt;span style="color: blue"&gt;As &lt;/span&gt;IDataServiceConfiguration)
        config.SetEntitySetAccessRule(&lt;span style="color: #a31515"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;, EntitySetRights.&lt;strong&gt;AllRead&lt;/strong&gt;)
    &lt;span style="color: blue"&gt;End Sub
End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now back on the client we can add the service reference to this service instead. After we add the service reference we can run the Report Wizard again by selecting “Design a New Report” smart tag on the ReportViewer control like I showed in the beginning. Select Object as the data source (or Service if you didn’t add the service reference first, then you’ll have to click “Add Data Sources…” again and then select Object) and you should see the list of entities exposed in the NorthwindReport data model. Now when we select Customer, we don’t have a problem.&lt;/p&gt;

&lt;p&gt;Design the report how you like (&lt;a href="http://msdn.microsoft.com/en-us/library/bb558708.aspx" target="_blank"&gt;see the documentation for more details&lt;/a&gt;) by clicking through the wizard and then go back to the smart tag on the ReportViewer and you should see the report you just created in the dropdown. Next go to the code-behind for the form and in the Load handler we just set the BindingSource.DataSource property to the results of the ADO.NET Data Service LINQ query:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;NorthwindClient.NorthwindReportService

&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Form1

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;Form1_Load() &lt;span style="color: blue"&gt;Handles MyBase&lt;/span&gt;.Load
        &lt;span style="color: green"&gt;'TODO: put in My.Settings
        &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;uri &lt;span style="color: blue"&gt;As New &lt;/span&gt;Uri(&lt;span style="color: #a31515"&gt;&amp;quot;http://localhost:1933/NorthwindReport.svc/&amp;quot;&lt;/span&gt;)
        &lt;span style="color: green"&gt;'Create the service reference
        &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;db &lt;span style="color: blue"&gt;As New &lt;/span&gt;NorthwindReportEntities(uri)

        &lt;span style="color: green"&gt;'Set the report's DataSource to the results of the query
        &lt;/span&gt;&lt;span style="color: blue"&gt;Me&lt;/span&gt;.BindingSource.DataSource = &lt;span style="color: blue"&gt;From &lt;/span&gt;c &lt;span style="color: blue"&gt;In &lt;/span&gt;db.Customers _
                                      &lt;span style="color: blue"&gt;Where &lt;/span&gt;c.Country = &lt;span style="color: #a31515"&gt;&amp;quot;USA&amp;quot; &lt;/span&gt;_
                                      &lt;span style="color: blue"&gt;Order By &lt;/span&gt;c.CompanyName

        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.ReportViewer1.RefreshReport()
    &lt;span style="color: blue"&gt;End Sub
End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Now hit F5 to run this baby and you’ll see the report pull the data from the service and display in the form:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_18.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="352" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingtheReportViewerwith.NETDataServices_BC9A/image_thumb_8.png" width="557" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recap &amp;amp; Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ADO.NET Data Services are a great way to quickly and easily expose data on the web, especially if it’s just read-only data used for remote reporting clients. The key to using the ReportViewer with ADO.NET Data Services (or an Entity Data Model directly, or even your own object model) is to make sure there are &lt;strong&gt;no &lt;/strong&gt;many-to-many associations on the entities. Here are the resources you need to get started with ReportViewer and ADO.NET Data Services:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/cc668796.aspx" target="_blank"&gt;Data Service Quick Start (ADO.NET Data Services Framework)&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/cc668183.aspx" target="_blank"&gt;How to: Add, Update, or Remove an ADO.NET Service Reference&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms251704.aspx" target="_blank"&gt;Configuring ReportViewer for Local Processing&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb558708.aspx" target="_blank"&gt;Report Designer (Visual Studio)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9876342" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Entity+Framework/default.aspx">Entity Framework</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Reporting/default.aspx">Reporting</category></item><item><title>Using Windows Presentation Foundation in Office Clients</title><link>http://blogs.msdn.com/bethmassi/archive/2009/08/10/using-windows-presentation-foundation-in-office-clients.aspx</link><pubDate>Tue, 11 Aug 2009 03:31:51 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9863656</guid><dc:creator>Beth Massi</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9863656.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9863656</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9863656</wfw:comment><description>&lt;p&gt;&lt;img style="display: inline; margin: 0px 10px 10px 0px" src="http://www.sdn.nl/Portals/0/Upload/Images/2009/Website/VP101.png" align="left" /&gt; I was cleaning up my desk today and in the piles of mail and gobs of paper I found the &lt;a href="http://www.sdn.nl/SDN/Magazine/tabid/66/articleType/ArticleView/articleId/2870/SDN-Magazine-101-Women-In-Technology-is-uit.aspx" target="_blank"&gt;SDN Magazine “Women in Technology” issue 101&lt;/a&gt; that featured an article I wrote that was released in print back in May. Well, I just noticed today that near the end of June they made most of the articles available online, including mine. :-)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.sdn.nl/SDN/Artikelen/tabid/58/agentType/View/PropertyID/2982/Default.aspx"&gt;&lt;strong&gt;Using Windows Presentation Foundation and Line-of-Business Data in Microsoft Office Clients&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In this article I talk about how to expose Line-of-Business data via ADO.NET Data Services to an Excel client using WPF. Office solutions you build with Visual Studio are designed to work with Windows Forms controls but you can also use WPF controls in your solutions as well. Any UI element that can host Windows Forms controls in an Office solution (VSTO) can also host WPF controls using the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx" target="_blank"&gt;Winforms ElementHost&lt;/a&gt; as a container. &lt;/p&gt;  &lt;p&gt;Using WPF controls in Office allows you to think out of the box and provide world-class data visualizations that are not possible with Windows Forms controls. And you can do it easily in an instantly familiar end-user application like those in the Office family. But what if you don’t have any fancy data visualizations? Even the simplest controls that display data are often better off as WPF controls in Office applications because they better match the UI styles used in the latest versions of Office. Using WPF can make your add-ins look built into the Office applications themselves, providing a better user experience.&lt;/p&gt;  &lt;p&gt;This article describes one piece of the Northwind Office Business Application (OBA) we created in the beginning of the year so if you’re interested in OBA development with Outlook, Word, Excel and Sharepoint I’d suggest reading these as well:&lt;/p&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx"&gt;OBA Part 1 - Exposing Line-of-Business Data&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/07/oba-part-2-building-and-outlook-client-against-lob-data.aspx"&gt;OBA Part 2 - Building and Outlook Client against LOB Data&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/12/oba-part-3-storing-and-reading-data-in-word-documents.aspx"&gt;OBA Part 3 - Storing and Reading Data in Word Documents&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/03/08/oba-part-4-building-an-excel-client-against-lob-data.aspx"&gt;OBA Part 4 - Building an Excel Client against LOB Data&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/04/21/oba-part-5-building-the-sharepoint-2007-workflow.aspx"&gt;OBA Part 5 - Building the SharePoint 2007 Workflow&lt;/a&gt;&lt;/li&gt;  &lt;p&gt;The full sample application, built with Visual Studio 2008, is here: &lt;a title="http://code.msdn.microsoft.com/OBANorthwind" href="http://code.msdn.microsoft.com/OBANorthwind"&gt;http://code.msdn.microsoft.com/OBANorthwind&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Of course, the rest of the magazine is pack full of awesome articles from very well known women in technology (scroll to the bottom of &lt;a href="http://www.sdn.nl/SDN/Magazine/tabid/66/articleType/ArticleView/articleId/2870/SDN-Magazine-101-Women-In-Technology-is-uit.aspx" target="_blank"&gt;this page&lt;/a&gt; for the whole list). I’m honored to be featured with them in this issue. Thanks again to &lt;a href="http://information-worker.org/aboutus.aspx" target="_blank"&gt;Marianne van Wanrooij&lt;/a&gt; and the folks at &lt;a href="http://www.sdn.nl" target="_blank"&gt;SDN&lt;/a&gt; for putting this together and I’ll see you &lt;a href="http://www.sdc.nl/" target="_blank"&gt;in October at the SDN Conference&lt;/a&gt;!&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9863656" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/XML/default.aspx">XML</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Office/default.aspx">Office</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/OBA/default.aspx">OBA</category></item><item><title>OBA Part 5 - Building the SharePoint 2007 Workflow</title><link>http://blogs.msdn.com/bethmassi/archive/2009/04/21/oba-part-5-building-the-sharepoint-2007-workflow.aspx</link><pubDate>Wed, 22 Apr 2009 08:06:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9561302</guid><dc:creator>Beth Massi</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9561302.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9561302</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9561302</wfw:comment><description>&lt;p&gt;In my last few app building posts we've been building a simple Office Business Application (OBA) for the new Northwind Traders. If you missed them:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx"&gt;OBA Part 1 - Exposing Line-of-Business Data&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/07/oba-part-2-building-and-outlook-client-against-lob-data.aspx"&gt;OBA Part 2 - Building and Outlook Client against LOB Data&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/12/oba-part-3-storing-and-reading-data-in-word-documents.aspx"&gt;OBA Part 3 - Storing and Reading Data in Word Documents&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/03/08/oba-part-4-building-an-excel-client-against-lob-data.aspx" target="_blank"&gt;OBA Part 4 - Building an Excel Client against LOB Data&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Today we're going to build out the SharePoint workflow using Visual Studio 2008 SharePoint 2007 workflow templates. There's a plethora of &lt;a href="http://msdn.microsoft.com/en-us/library/bb386211.aspx" target="_blank"&gt;information on building these in the MSDN library&lt;/a&gt;. In order to develop against SharePoint you will need to set up your development environment properly so I &lt;a href="http://msdn.microsoft.com/en-us/library/cc160738.aspx" target="_blank"&gt;would read this first&lt;/a&gt; if you're just getting started. My SharePoint development environment is a 32bit Windows 2008 Server running MOSS 2007 and Visual Studio Professional 2008 Service Pack 1. &lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OBASPDiagram1_4.jpg"&gt;&lt;img title="OBASPDiagram1" style="border-right: 0px; border-top: 0px; display: inline; margin: 10px 0px 0px 5px; border-left: 0px; border-bottom: 0px" height="342" alt="OBASPDiagram1" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OBASPDiagram1_thumb_1.jpg" width="420" align="right" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If you recall &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/02/building-an-office-business-application-for-techready-8.aspx"&gt;our architecture diagram of our Northwind Traders OBA&lt;/a&gt; involved our Sales Reps submitting purchase orders as Word 2007 documents up to SharePoint which kicked off a workflow to parse the document and update the database with the order data through our data service. This allows us to store the unstructured document on SharePoint and the structured order data in our database. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/12/oba-part-3-storing-and-reading-data-in-word-documents.aspx" target="_blank"&gt;In Part 3&lt;/a&gt; we built the code that does the parsing of the document, now we just need to get that code into our workflow. We’ll also build in a delay so that the workflow can check the database later to see if the order has been shipped and update the status appropriately. We’ll also take advantage of SharePoint’s workflow history and task list to report outcomes or any issues that may arise.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Creating a Document Library for the Purchase Order Documents&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;For this example we need to add a document library called &lt;em&gt;Orders &lt;/em&gt;for the purchase order documents that are submitted. To create the document library, navigate to your SharePoint site and then in the right-had upper corner drop down the Site Actions, select Create (or just navigate to /_layouts/create.aspx) and then under Libraries select &lt;em&gt;Document Library. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA1A_2.jpg"&gt;&lt;img title="SPOBA1A" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="386" alt="SPOBA1A" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA1A_thumb.jpg" width="661" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The only other property that I changed here is the document template, change that to &lt;em&gt;Microsoft Office Word Document &lt;/em&gt;and then hit the Create button. This will bring you to the doc library and you’ll see the default fields in the column headers. We’re going to need to modify these to show the Order Status, an Order Number, the Shipped Date and the email address of the Sales Rep that submitted the order.&lt;/p&gt;  &lt;p&gt;Click on Settings then select &lt;em&gt;Create column&lt;/em&gt; to create new columns for the orders in the document library. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA2A_2.jpg"&gt;&lt;img title="SPOBA2A" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="443" alt="SPOBA2A" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA2A_thumb.jpg" width="659" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;For this example I added the following columns:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;em&gt;Order Status&amp;#160; &lt;br /&gt;&lt;/em&gt;Choice (New, Processed, Shipped, On Hold, Canceled)       &lt;br /&gt;Required = &lt;b&gt;No        &lt;br /&gt;&lt;/b&gt;Default = New       &lt;br /&gt;Add to Default View &lt;/li&gt;    &lt;li&gt;&lt;em&gt;Order Number&lt;/em&gt;       &lt;br /&gt;Single line of text       &lt;br /&gt;Required = &lt;b&gt;No&amp;#160; &lt;br /&gt;&lt;/b&gt;Add to Default View &lt;/li&gt;    &lt;li&gt;&lt;em&gt;Shipped Date        &lt;br /&gt;&lt;/em&gt;Date Only (no Time)       &lt;br /&gt;Required = &lt;strong&gt;No        &lt;br /&gt;&lt;/strong&gt;Add to Default View &lt;/li&gt;    &lt;li&gt;&lt;em&gt;Sales Rep Email        &lt;br /&gt;&lt;/em&gt;Single line of text       &lt;br /&gt;Required = &lt;b&gt;Yes&amp;#160; &lt;br /&gt;&lt;/b&gt;Add to Default View &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA3A_2.jpg"&gt;&lt;img title="SPOBA3A" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="419" alt="SPOBA3A" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA3A_thumb.jpg" width="596" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;After I added these columns I added a new default view to display them in the order I want. Click on the Settings again and select C&lt;em&gt;reate view.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA4_2.jpg"&gt;&lt;img title="SPOBA4" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="200" alt="SPOBA4" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA4_thumb.jpg" width="647" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The only thing the user is required to fill out when they upload a new purchase order document is the sales rep’s email address. (Recall that we added this field to the database &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx" target="_blank"&gt;when we built the data service&lt;/a&gt;). The Order Status and Shipped Date will actually be filled out automatically by the workflow depending on whether the order is new or has been updated by the Excel client (&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/03/08/oba-part-4-building-an-excel-client-against-lob-data.aspx" target="_blank"&gt;which we built in the last OBA post&lt;/a&gt;) that the shipping department uses to mark orders as shipped. Order Number will also be assigned by the workflow. We’ll use this to correlate the data with the purchase order document here in the list so we’ll need to add this field to the database. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Adding the Order Number to Northwind &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;So now we have the document library set up, we’re almost ready to write the workflow. First we’ll need to add the OrderNumber field to the Orders table in the Northwind database and then refresh our data service service so that this starts to show up as an available field on the Order. &lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;USE &lt;/span&gt;Northwind
GO

&lt;span style="color: blue"&gt;ALTER TABLE &lt;/span&gt;dbo.Orders &lt;span style="color: blue"&gt;ADD
    &lt;/span&gt;OrderNumber &lt;span style="color: blue"&gt;nvarchar&lt;/span&gt;(25) &lt;span style="color: blue"&gt;NULL
&lt;/span&gt;GO&lt;/pre&gt;

&lt;p&gt;In order to pick up this new field we need to refresh the Entity Data Model behind our data service. In the NorthwindDataService project open the NorthwindModel.edmx and then right-click on the design surface and select &lt;em&gt;Refresh from database. &lt;/em&gt;This will pick up the OrderNumber field on the Order entity. Rebuild the data service. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Options on Hosting the Data Service for Workflow Development&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’ve been following along and playing with &lt;a href="http://code.msdn.microsoft.com/OBANorthwind"&gt;the sample&lt;/a&gt;, you’ll notice that the NorthwindDataService project is currently set to be hosted in the ASP.NET development server right now so that testing the Excel and Outlook clients is easy. However at this point you may opt to deploy this to IIS instead so that you don’t have to remember to start it up manually every time you want to test the SharePoint Workflow. And of course for deployment to production you’ll need to host it in IIS anyway. &lt;/p&gt;

&lt;p&gt;It gets slightly tricky if you want to host the data service in IIS on the same server as SharePoint because SharePoint takes over Port 80. So the easiest thing to do is to open IIS Manager and just create a new web site on Port 82 called NorthwindHost and then create a new application virtual directory called Northwind under that. By default, when you create a new web site it should also create a new Application Pool for you running under the identity NETWORK SERVICE. The identity you use here will need to have read and execute file permissions on the physical locations of any virtual directories you create as well as proper database permissions. &lt;/p&gt;

&lt;p&gt;It’s XCOPY deployment at that point. Just copy the Web.Config, Northwind.svc and the \bin directory over to the physical location of the Northwind virtual directory and you should be good to go.&amp;#160; You can do this in Visual Studio (if running as an administrator) just right-click on the NorthwindDataService project in the solution explorer and then select publish. Then enter http://localhost:82/Northwind/ (or whatever you named it) and it will build and publish the files there automatically. &lt;/p&gt;

&lt;p&gt;Note however, that before the WCF service will activate you have to install the WCF service handlers into IIS. These may not be installed automatically so in Windows 2008 check the Server Manager, scroll down to the Features Summary and select “Add Features”. Then expand the first node “.NET&amp;#160; 3.0 Features” and check WCF Activation. &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Remember if you change the location of the data service then you need to update the settings in the Excel and Outlook client (app.config file). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating the SharePoint Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’re not doing this already, restart Visual Studio and &lt;strong&gt;Run as Administrator&lt;/strong&gt;. This is necessary so that you can deploy and debug your workflow. Next add a new project to the solution, File –&amp;gt; Add –&amp;gt; New Project. For this example we’re just going to create a simple SharePoint 2007 Sequential Workflow. (Note: You will need Visual Studio 2008 Professional and higher to get these templates.)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA6_2.jpg"&gt;&lt;img title="SPOBA6" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="352" alt="SPOBA6" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA6_thumb.jpg" width="546" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As I mentioned before the workflow will kick off when a new purchase order is added to the document library in order to parse the data in the document. So when the order is first added to the list it will have a status of &lt;strong&gt;New&lt;/strong&gt;. After it is parsed we will set the status to &lt;strong&gt;Processed&lt;/strong&gt;, which happens right away. Later, after the shipping department enters the shipped date in the Excel client and updates the Orders.ShippedDate field in the database, we need the workflow to wake back up and set the order status to &lt;strong&gt;Shipped&lt;/strong&gt;. For this example I’m going to build a delay into the workflow to check the database (via our data service) every so often. For testing it can be a couple minutes but once we deploy we can set it to every couple hours. Note that if you’re building more statuses or states into your own workflows you may want to take a look at the State Machine Workflow template instead. &lt;/p&gt;

&lt;p&gt;So the next step is to specify where your SharePoint site and document library resides, for development this is going to be http://&lt;em&gt;YourServerName. &lt;/em&gt;Once you specify the site you can then select the Orders document library in the Library dropdown. Leave “Automatically associate workflow?” checked so that Visual Studio can deploy the workflow to the site automatically for us. &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA8_2.jpg"&gt;&lt;img title="SPOBA8" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="273" alt="SPOBA8" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA8_thumb.jpg" width="345" border="0" /&gt;&lt;/a&gt; &lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA9_2.jpg"&gt;&lt;img title="SPOBA9" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="275" alt="SPOBA9" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA9_thumb.jpg" width="344" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;On the next page check off how you want to start the workflow. For this example we’ll select “When an item is created”. You can also check “Manually by users” which can be helpful when testing but it’s not necessary for our example. Note that you can change these settings later on the Workflow project -- from the Project menu select “SharePoint debug settings..”. You need to be running Visual Studio as an administrator to open these settings. &lt;strong&gt;You’ll need to do this if you’re going to run the Workflow in the &lt;/strong&gt;&lt;a href="http://code.msdn.microsoft.com/OBANorthwind"&gt;&lt;strong&gt;sample code&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; against your own SharePoint site.&amp;#160; &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the project is created it will automatically add a workflow called Workflow1 and open the designer which will display an event activity for onWorkflowActivated. An OnWorkflowActivated activity must be the first activity in a Windows SharePoint Services workflow so Visual Studio automatically sets one up for us. I renamed Workflow1 to ProcessOrder in the Solution Explorer (I like descriptive names ;-)) which means I’ll also need to update the values for the CorrelationToken.OwnerActivityName as well as the WorkflowProperties.Name to set them to ProcessOrder: &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA10_2.jpg"&gt;&lt;img title="SPOBA10" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="260" alt="SPOBA10" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA10_thumb.jpg" width="709" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now you can start laying out the design of the workflow. If you have used the WF designer before then this part should be familiar. Take a look at your toolbox and you’ll see the SharePoint specific activities listed under the Workflow 3.0 and 3.5 tabs. The design of the workflow for this example will be simple. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA7_4.jpg"&gt;&lt;img title="SPOBA7" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="562" alt="SPOBA7" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA7_thumb_1.jpg" width="536" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;There are three main blocks to the workflow that we’re going to build:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;First is the parsing of the order data in the document which is a standard code activity that you find in the Windows Workflow v3.0 tab on the toolbox. &lt;/li&gt;

  &lt;li&gt;The second block is a standard While loop that contains a delay activity. This piece will periodically query the database until the Order.ShipDate is updated in the database by the Excel client. &lt;/li&gt;

  &lt;li&gt;The third block will be an IfElse activity which will check the Order status and either write an informational message to the History list in the case the order shipped successfully, otherwise we create a Task and assign it to the administrator for further investigation. The LogToHistoryListActivity and the CreateTask items can be found in the SharePoint Workflow tab on the toolbox. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before we start writing the workflow code, let’s create some constants that we can use to refer to the data service URI, our order statuses, and list column names (I just added a new Module called Constants.vb):&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Friend Module &lt;/span&gt;Constants
    &lt;span style="color: blue"&gt;Public Const &lt;/span&gt;OrderStatusColumn &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;Order Status&amp;quot;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Const &lt;/span&gt;OrderNumberColumn &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;Order Number&amp;quot;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Const &lt;/span&gt;ShippedDateColumn &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;Shipped Date&amp;quot;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Const &lt;/span&gt;SalesRepEmailColumn &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;Sales Rep Email&amp;quot;

    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Const &lt;/span&gt;NewStatus &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;New&amp;quot;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Const &lt;/span&gt;ShippedStatus &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;Shipped&amp;quot;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Const &lt;/span&gt;ProcessedStatus &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;Processed&amp;quot;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Const &lt;/span&gt;OnHoldStatus &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;On Hold&amp;quot;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Const &lt;/span&gt;CanceledStatus &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;Canceled&amp;quot;

&lt;/span&gt;&lt;span style="color: green"&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Const &lt;/span&gt;ServiceURL &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;http://localhost:82/NorthwindService/Northwind.svc&amp;quot;
&lt;/span&gt;&lt;span style="color: blue"&gt;End Module&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Parsing the Order Document &lt;strong&gt;(CodeActivity parseOrder) &lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Workflow kicks off immediately after a purchase order document is checked into the document library. The first code activity out of the gate is parsing the order document’s customXML for the order data we need. I already &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/12/oba-part-3-storing-and-reading-data-in-word-documents.aspx"&gt;demonstrated a simple console application for extracting the order data from a Word document in Part 3&lt;/a&gt;. This code uses the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c6e744e5-36e9-45f5-8d8c-331df206e0d0&amp;amp;DisplayLang=en"&gt;Open XML SDK&lt;/a&gt; so you’ll need to download that and install it on your SharePoint server so that the assemblies are in the GAC. Then add an assembly reference to DocumentFormat.OpenXML. &lt;/p&gt;

&lt;p&gt;From that console application project I copied the DocumentOderData.vb, Extensions.vb code files and the OrderEntry.xsd into the workflow project. Module1.vb had a method called ParseOrderDocument which parsed the docx file and populated a DocumentOrderData class with the information. I took that code and created a new class called Shredder and modified the interface a bit so that we could pass it a Microsoft.Sharepoint.SPFile class instead: &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;DocumentFormat.OpenXml.Packaging
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #b96464"&gt;xmlns&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;urn:microsoft:examples:oba&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;

&lt;/span&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Shredder

    &lt;span style="color: blue"&gt;Public Function &lt;/span&gt;ParseOrderDocument(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;docFile &lt;span style="color: blue"&gt;As &lt;/span&gt;SPFile) &lt;span style="color: blue"&gt;As &lt;/span&gt;DocumentOrderData
        &lt;span style="color: blue"&gt;Using &lt;/span&gt;docStream = docFile.OpenBinaryStream
            &lt;span style="color: blue"&gt;Return &lt;/span&gt;ParseOrderDocument(WordprocessingDocument.Open(docStream, &lt;span style="color: blue"&gt;False&lt;/span&gt;))
        &lt;span style="color: blue"&gt;End Using
    End Function

&lt;/span&gt;&lt;span style="color: gray"&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Function &lt;/span&gt;ParseOrderDocument(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;wordDoc &lt;span style="color: blue"&gt;As &lt;/span&gt;WordprocessingDocument) &lt;span style="color: blue"&gt;As &lt;/span&gt;DocumentOrderData&lt;br /&gt;...&lt;/pre&gt;

&lt;p&gt;We also had a means for adding this data to the database via a method called AddNewOrder. The only change we need here is to create a unique OrderNumber string, add it to the Order entity, and return it to the workflow so we can also set it on the list item in SharePoint. You can decide how you want to generate unique order numbers, whether you want them to be GIUDs or timestamps or some other random number. I like using a combination of the CustomerID and the current date&amp;amp;time so that it’s human readable.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;orderNum = Replace(Replace(Replace(cust.CustomerID &amp;amp; Now.ToString(), &lt;span style="color: #a31515"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;), &lt;span style="color: #a31515"&gt;&amp;quot;:&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;), &lt;span style="color: #a31515"&gt;&amp;quot; &amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;This will work as long as there aren’t two orders for the same customer submitted within the same second so depending on your actual scenario you may opt for a different strategy :-). So this AddNewOrder code I placed into a class called OrderManager which also encapsulates all calls to the data service. Speaking of our data service, we’ll need to add a Service Reference to the workflow project called NorthwindService (right-click on the workflow project and select Add Service Reference) which will add the database entity types to our project. &lt;/p&gt;

&lt;p&gt;Now drop a CodeActivity onto the Workflow designer and in the properties window name it parseOrder. Then right-click on it in the designer and select Generate Handlers to automatically generate the parseOrder_ExecuteCode handler. If the order data is extracted and added to the database successfully then an order number is assigned and the status is set to Processed. If the document does not contain the &amp;lt;OrderEntry&amp;gt; CustomXML then the status will be set to Canceled. If there is a problem adding the data to the database then the status is set to On Hold. (Notice that this code also uses the Application.Log to write messages to the Event Log which you can &lt;a href="http://msdn.microsoft.com/en-us/library/07347hdt.aspx"&gt;see how to set up here&lt;/a&gt;.)&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;ProcessOrder
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;SequentialWorkflowActivity

    &lt;span style="color: blue"&gt;Public &lt;/span&gt;workflowProperties &lt;span style="color: blue"&gt;As New &lt;/span&gt;SPWorkflowActivationProperties
    &lt;span style="color: blue"&gt;Public Sub New&lt;/span&gt;()
        &lt;span style="color: blue"&gt;MyBase&lt;/span&gt;.New()
        InitializeComponent()
    &lt;span style="color: blue"&gt;End Sub

    Private Sub &lt;/span&gt;parseOrder_ExecuteCode(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As &lt;/span&gt;System.Object, _
                                       &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;System.EventArgs)
        &lt;span style="color: green"&gt;'This method is executed once the purchase order is uploaded 
        ' and checked into the document library 
        &lt;/span&gt;&lt;span style="color: blue"&gt;Try
            Dim &lt;/span&gt;orderNumber &lt;span style="color: blue"&gt;As String &lt;/span&gt;= &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;
            &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;shredder &lt;span style="color: blue"&gt;As New &lt;/span&gt;Shredder

            &lt;span style="color: green"&gt;'Valid OrderStatus: New, Processed, Shipped, Cancelled, On Hold
            ' (See Constants.vb for column and status strings)
            &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;status = workflowProperties.Item(OrderStatusColumn).ToString()

            &lt;span style="color: blue"&gt;If &lt;/span&gt;status = NewStatus &lt;span style="color: blue"&gt;Then
                &lt;/span&gt;&lt;span style="color: green"&gt;'Get order data out of the document
                &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;docData = shredder.ParseOrderDocument(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item.File)

                &lt;span style="color: blue"&gt;If &lt;/span&gt;docData &lt;span style="color: blue"&gt;IsNot Nothing Then
                    Dim &lt;/span&gt;manager &lt;span style="color: blue"&gt;As New &lt;/span&gt;OrderManager
                    &lt;span style="color: blue"&gt;Dim &lt;/span&gt;employeeEmail = workflowProperties.Item(SalesRepEmailColumn).ToString()

                    &lt;span style="color: green"&gt;'Add order data to the DB (through the service) and return the order number.
                    &lt;/span&gt;orderNumber = manager.AddNewOrder(docData, employeeEmail)

                    &lt;span style="color: blue"&gt;If &lt;/span&gt;orderNumber &amp;lt;&amp;gt; &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;Then
                        &lt;/span&gt;status = ProcessedStatus
                        &lt;span style="color: blue"&gt;My&lt;/span&gt;.Application.Log.WriteEntry( _
                            &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Order {0} added to database successfully.&amp;quot;&lt;/span&gt;, _
                                          orderNumber), TraceEventType.Information)
                    &lt;span style="color: blue"&gt;Else
                        &lt;/span&gt;status = OnHoldStatus
                        &lt;span style="color: blue"&gt;My&lt;/span&gt;.Application.Log.WriteEntry( _
                            &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Order could not be added to database for {0}.&amp;quot;&lt;/span&gt;, _
                                          &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item.Name), TraceEventType.Error)
                    &lt;span style="color: blue"&gt;End If
                Else
                    &lt;/span&gt;status = CanceledStatus
                    &lt;span style="color: blue"&gt;My&lt;/span&gt;.Application.Log.WriteEntry( _
                        &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Invalid purchase order submitted for {0}&amp;quot;&lt;/span&gt;, _
                                      &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item.Name), TraceEventType.Error)
                &lt;span style="color: blue"&gt;End If
            End If

            If &lt;/span&gt;status &amp;lt;&amp;gt; &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;Then
                Me&lt;/span&gt;.workflowProperties.Item(OrderStatusColumn) = status
                &lt;span style="color: blue"&gt;If &lt;/span&gt;orderNumber.Length() &amp;gt; 0 &lt;span style="color: blue"&gt;Then
                    Me&lt;/span&gt;.workflowProperties.Item(OrderNumberColumn) = orderNumber
                &lt;span style="color: blue"&gt;End If
                Me&lt;/span&gt;.workflowProperties.Item.Update()
            &lt;span style="color: blue"&gt;End If

        Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            &lt;span style="color: blue"&gt;My&lt;/span&gt;.Application.Log.WriteException(ex)
        &lt;span style="color: blue"&gt;End Try

    End Sub&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now that the order is in the database, you can open &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/03/08/oba-part-4-building-an-excel-client-against-lob-data.aspx"&gt;the Excel client we wrote in part 4&lt;/a&gt; and enter a ShippedDate and click save to update the order. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Querying the Database Periodically (&lt;strong&gt;WhileActivity waitForProcessed&lt;/strong&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next we need a WhileActivity so that we can check the database to see if the ShippedDate has been updated. Drag a standard While activity from the toolbox under the parseOrder and name it waitForProcessed in the properties window. Right-click on the designer and select View Code and write the following method:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;    Private Sub &lt;/span&gt;orderProcessed(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As &lt;/span&gt;System.Object, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;ConditionalEventArgs)
      &lt;span style="color: blue"&gt;Try
            Dim &lt;/span&gt;status = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item(OrderStatusColumn).ToString()
            &lt;span style="color: blue"&gt;Dim &lt;/span&gt;orderNumber = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item(Constants.OrderNumberColumn).ToString()

            &lt;span style="color: blue"&gt;If &lt;/span&gt;status &amp;lt;&amp;gt; ProcessedStatus &lt;span style="color: blue"&gt;Then
                &lt;/span&gt;&lt;span style="color: green"&gt;'End while branch and go to next step in sequence if status is:
                '  Canceled = invalid purchase order (no &amp;lt;OrderEntry&amp;gt; CustomXML found)
                '  On Hold = Could not add data to database (see error log for details)
                &lt;/span&gt;e.Result = &lt;span style="color: blue"&gt;False
            Else
                &lt;/span&gt;&lt;span style="color: green"&gt;'Get order from DB
                &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;manager &lt;span style="color: blue"&gt;As New &lt;/span&gt;OrderManager
                &lt;span style="color: blue"&gt;Dim &lt;/span&gt;processedOrder = manager.GetOrder(orderNumber)

                &lt;span style="color: green"&gt;'If order was shipped (ShippedDate not NULL) then set Order Status to Shipped.
                &lt;/span&gt;&lt;span style="color: blue"&gt;If &lt;/span&gt;processedOrder &lt;span style="color: blue"&gt;IsNot Nothing Then
                    If &lt;/span&gt;processedOrder.ShippedDate &lt;span style="color: blue"&gt;IsNot Nothing AndAlso &lt;/span&gt;_
                       processedOrder.ShippedDate.HasValue &lt;span style="color: blue"&gt;Then
                        My&lt;/span&gt;.Application.Log.WriteEntry( _
                            &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Order {0} has shipped as of {1}&amp;quot;&lt;/span&gt;, _
                                          orderNumber, Now()), TraceEventType.Information)

                        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item(OrderStatusColumn) = ShippedStatus
                        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item(ShippedDateColumn) = processedOrder.ShippedDate
                        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item.Update()
                        &lt;span style="color: green"&gt;'end while branch and go to next step in sequence
                        &lt;/span&gt;e.Result = &lt;span style="color: blue"&gt;False
                    Else
                        My&lt;/span&gt;.Application.Log.WriteEntry( _
                            &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Order {0} has not shipped as of {1}&amp;quot;&lt;/span&gt;, _
                                          orderNumber, Now()), TraceEventType.Warning)
                        &lt;span style="color: green"&gt;'keep workflow running until shipped or canceled
                        &lt;/span&gt;e.Result = &lt;span style="color: blue"&gt;True
                    End If
                Else
                    My&lt;/span&gt;.Application.Log.WriteEntry( _
                        &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Order {0} has been deleted from the database&amp;quot;&lt;/span&gt;, _
                                      orderNumber, Now()), TraceEventType.Error)&lt;br /&gt;
                    &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item(OrderStatusColumn) = CanceledStatus
                    &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item.Update()
                    &lt;span style="color: green"&gt;'end while branch and go to next step in sequence
                    &lt;/span&gt;e.Result = &lt;span style="color: blue"&gt;False
                End If
            End If

        Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            &lt;span style="color: blue"&gt;My&lt;/span&gt;.Application.Log.WriteException(ex)
        &lt;span style="color: blue"&gt;End Try

    End Sub&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Notice in this code we’re referring to a method on the OrderManager called GetOrder which simply queries the Order entity from the database via the data service using LINQ:&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;OBADemoWorkflow.NorthwindServiceReference

&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;OrderManager
    &lt;span style="color: blue"&gt;Private &lt;/span&gt;ctx &lt;span style="color: blue"&gt;As New &lt;/span&gt;NorthwindEntities(&lt;span style="color: blue"&gt;New &lt;/span&gt;Uri(Constants.ServiceURL))&lt;br /&gt;
&lt;span style="color: blue"&gt;    Public Function &lt;/span&gt;AddNewOrder(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;docData &lt;span style="color: blue"&gt;As &lt;/span&gt;DocumentOrderData, _&lt;br /&gt;                                &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;employeeEmail &lt;span style="color: blue"&gt;As String&lt;/span&gt;) &lt;span style="color: blue"&gt;As String...

&lt;/span&gt;&lt;span style="color: gray"&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Function &lt;/span&gt;GetOrder(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;orderNumber &lt;span style="color: blue"&gt;As String&lt;/span&gt;) &lt;span style="color: blue"&gt;As &lt;/span&gt;Order
        &lt;span style="color: blue"&gt;Try
            Dim &lt;/span&gt;theOrder = (&lt;span style="color: blue"&gt;From &lt;/span&gt;o &lt;span style="color: blue"&gt;In &lt;/span&gt;ctx.Orders _
                            &lt;span style="color: blue"&gt;Where &lt;/span&gt;o.OrderNumber = orderNumber).FirstOrDefault()

            &lt;span style="color: blue"&gt;Return &lt;/span&gt;theOrder

        &lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            &lt;span style="color: blue"&gt;My&lt;/span&gt;.Application.Log.WriteException(ex)
            &lt;span style="color: blue"&gt;Return Nothing
        End Try
    End Function
End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA11_2.jpg"&gt;&lt;img title="SPOBA11" style="border-right: 0px; border-top: 0px; display: inline; margin: 0px 10px 0px 0px; border-left: 0px; border-bottom: 0px" height="166" alt="SPOBA11" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA11_thumb.jpg" width="233" align="left" border="0" /&gt;&lt;/a&gt; Now you can go back to the designer and set the Condition on the waitForProcessed WhileActivity to the orderProcessed method. Set the Condition to a Code Condition and the dropdown will contain only those methods that have the right signature, i.e. have a ConditionalEventArgs parameter. The orderProcessed method will set the e.Result = True only if the order is in the Processed state, is still in the database, and its ShippedDate is still NULL. This means that the While activity will continue to run. &lt;/p&gt;

&lt;p&gt;Because the shipping department most likely will not ship the order out the door the second the order is entered into the database (&amp;lt;g&amp;gt;), we need a way for our workflow to delay and check periodically. Depending on your business you may want to check hourly or even daily. For testing you probably want to check every minute or two. This is where the DelayActivity comes in. Drag a standard Delay activity onto the designer inside the While Activity and set the Timeout Duration in the properties window to 3 minutes or so. &lt;/p&gt;

&lt;p&gt;Before we go on I want to mention that there were known issues with the Delay activities not firing correctly in SharePoint that are addressed by this KB Article: &lt;a title="http://support.microsoft.com/kb/953630/" href="http://support.microsoft.com/kb/953630/"&gt;http://support.microsoft.com/kb/953630/&lt;/a&gt;. The SharePoint timer service (OWSTIMER.exe) is set to only wake up every 5 minutes, so you probably want to set that to a shorter interval in your testing environment otherwise you’ll have to wait at least 5 minutes no matter how short you set your Delay activity. Another other issue I noticed was sometimes on rebuild &amp;amp; redeployment I needed to restart the timer service manually from an admin command prompt:&lt;/p&gt;

&lt;p&gt;&amp;gt;Net Stop SPTimerV3
  &lt;br /&gt;&amp;gt;iisreset

  &lt;br /&gt;&amp;gt;Net Start SPTimerV3&lt;/p&gt;

&lt;p&gt;Also there is an issue with debugging delays. I couldn’t just press F5 to debug the workflow after the delay. Up until that point I debugged just fine (which is where almost all our code is in this example) but if I wanted to see the rest of the code execute after the delay then I needed to attach to the OWSTIMER.exe process (while you’re debugging, on the main menu select Tools –&amp;gt; Attach to Process). This is also one of&amp;#160; the reasons why I enabled the Application.Log to send messages to the Event Log. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrapping Up the Workflow (History Logging and Creating Tasks)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The last piece of the workflow is simple, if the order is shipped we’ll just log a message to the workflow history list otherwise we’ll create a task for the administrator to investigate. Drop an IfElse activity under the While activity set and name it checkIfShipped. Then name the first branch ifShipped and the second branch elseNotShipped. In the ifShipped branch drop a LogToHistoryListActivity which is found in the SharePoint Workflow tab on the Toolbox. In the elseNotShipped drop a CreateTask activity. On the properties window for the CreateTask create a new field binding for both the TaskID and TaskProperties and enter a correlationToken with the parent activity set to ProcessOrder (the workflow). &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA12_2.jpg"&gt;&lt;img title="SPOBA12" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="297" alt="SPOBA12" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/SPOBA12_thumb.jpg" width="709" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Then right-click on both the CreateTask and LogToHistoryActivity and select Generate Handlers in order to generate the method stubs for each of them. We’ll also need a method called isOrderShipped with the same signature as the orderProcessed method above to be able to set it as the Code Condition of the ifShipped branch. We need to check the workflowProperties.Item for the order status and set the e.Result = True if the status is Shipped. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;isOrderShipped(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As Object&lt;/span&gt;, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;ConditionalEventArgs)
&lt;span style="color: green"&gt;    'Returns True if Order Status equals Shipped
    &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;status = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item(OrderStatusColumn).ToString()
    e.Result = (status = ShippedStatus)
&lt;span style="color: blue"&gt;End Sub

Private Sub &lt;/span&gt;createTask1_MethodInvoking(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As &lt;/span&gt;System.Object, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;System.EventArgs)
    &lt;span style="color: blue"&gt;Try
        &lt;/span&gt;&lt;span style="color: green"&gt;'This will execute if the workflow is ending but the Order Status 
        ' is not Shipped (i.e. Canceled or On Hold). 
        ' This code creates a workflow task item so the AssignedTo can investigate.
        &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;status = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item(OrderStatusColumn).ToString()
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;name = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.workflowProperties.Item.Name

        createTask1_TaskId1 = Guid.NewGuid()
        createTask1_TaskProperties1.AssignedTo = &lt;span style="color: #a31515"&gt;&amp;quot;obavm09\wssdeveloper&amp;quot;
        &lt;/span&gt;createTask1_TaskProperties1.Title = &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Problem with order {0}&amp;quot;&lt;/span&gt;, name)
        createTask1_TaskProperties1.Description = &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Order {0} as of {1}&amp;quot;&lt;/span&gt;, status, Now)
    &lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
        &lt;span style="color: blue"&gt;My&lt;/span&gt;.Application.Log.WriteException(ex)
    &lt;span style="color: blue"&gt;End Try
End Sub

Private Sub &lt;/span&gt;logToHistoryListActivity1_MethodInvoking(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As &lt;/span&gt;System.Object, _&lt;br /&gt;                                                     &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;System.EventArgs)
    logToHistoryListActivity1.HistoryOutcome = &lt;span style="color: #a31515"&gt;&amp;quot;Order has been shipped.&amp;quot;
&lt;/span&gt;&lt;span style="color: blue"&gt;End Sub&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;Testing the Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Visual Studio (still running as Administrator) Rebuild the solution. Then right-click on the OBADemoWorkflow project and select Deploy from the context menu. Now we can head over to the document library and upload some purchase orders. I used the one we created previously in &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/12/oba-part-3-storing-and-reading-data-in-word-documents.aspx"&gt;Part 3&lt;/a&gt; with ALFKI as the CustomerID. Go to the Orders document library, click Upload, Browse for the purchase order and click OK. Then fill out the required field Sales Rep Email (this is the Employee.EmailAddress field we added to the database in &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx"&gt;Part 1&lt;/a&gt;). Once you click “Check In” the workflow will kick off. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OrderWorkflow1_2.jpg"&gt;&lt;img title="OrderWorkflow1" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="352" alt="OrderWorkflow1" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OrderWorkflow1_thumb.jpg" width="639" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The Order status is first set to “New”….&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OrderWorkflow2_2.jpg"&gt;&lt;img title="OrderWorkflow2" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="352" alt="OrderWorkflow2" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OrderWorkflow2_thumb.jpg" width="663" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;But if you quickly refresh the list you will see that the Order Status and Order Number change as the order is processed and entered into the database. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OrderWorkflow3_2.jpg"&gt;&lt;img title="OrderWorkflow3" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="352" alt="OrderWorkflow3" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OrderWorkflow3_thumb.jpg" width="658" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now the workflow is in its delay activity waiting for us to update the Order.ShippedDate. Open up the Excel client and enter something in the ShippedDate field and save the sheet (or manually modify the database). The next time the SharePoint timer runs it will waken our delay which will check the database again and set the status appropriately.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OrderWorkflow4_2.jpg"&gt;&lt;img title="OrderWorkflow4" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="352" alt="OrderWorkflow4" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildingtheSharePointWorkFlow_D714/OrderWorkflow4_thumb.jpg" width="661" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you select the OBADemoWorkflow status (the last column in the view which is added automatically for us when we deploy) then you can see the status message in the Workflow History list. To see a task get created you can perform the same process but instead of updating the ShippedDate, delete the Order from the database (or delete the OrderNumber) and the workflow will set the status to Canceled and you will see a task in the list instead. And remember in testing we set the delay to a few minutes but in production Northwind Traders will be good with a 12 hour delay (gourmet foods don’t ship that quickly ;-)). &lt;/p&gt;

&lt;p&gt;I’ve added this workflow to the &lt;a href="http://code.msdn.com/obanorthwind"&gt;sample code we’ve been building up on Code Gallery&lt;/a&gt; so have a look. I hope this real(er)-world, componentized sample has given you a good introduction into OBA and some of the awesome VSTO features of Visual Studio 2008. &lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9561302" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Office/default.aspx">Office</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Workflow/default.aspx">Workflow</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/OBA/default.aspx">OBA</category></item><item><title>OBA Part 4 - Building an Excel Client against LOB Data</title><link>http://blogs.msdn.com/bethmassi/archive/2009/03/08/oba-part-4-building-an-excel-client-against-lob-data.aspx</link><pubDate>Mon, 09 Mar 2009 01:45:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9466700</guid><dc:creator>Beth Massi</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9466700.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9466700</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9466700</wfw:comment><description>&lt;p&gt;In my last few app building posts we've been building a simple Office Business Application (OBA) for the new Northwind Traders. If you missed them:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx"&gt;OBA Part 1 - Exposing Line-of-Business Data&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/07/oba-part-2-building-and-outlook-client-against-lob-data.aspx"&gt;OBA Part 2 - Building and Outlook Client against LOB Data&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/12/oba-part-3-storing-and-reading-data-in-word-documents.aspx"&gt;OBA Part 3 - Storing and Reading Data in Word Documents&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;(In the &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/12/oba-part-3-storing-and-reading-data-in-word-documents.aspx" target="_blank"&gt;last post&lt;/a&gt; on OBA I mentioned we would build out the &lt;a href="http://msdn.microsoft.com/en-us/library/cc936628.aspx" target="_blank"&gt;SharePoint Workflow&lt;/a&gt; next but I realized that it's important to see how the Excel client works before we write the workflow, so that will be the next post.)&lt;/p&gt;  &lt;p&gt;In this post I want to focus on how we can build an Excel client for our shipping department. This will be a customized Excel spreadsheet that lists the orders that need to be shipped and allows users to enter the ship dates and save them back to the database. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcel1_4.jpg"&gt;&lt;img height="179" alt="OBAExcel1" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcel1_thumb_1.jpg" width="524" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;We'll also generate a pivot table and chart so that we can visualize the percentages of cities that we're shipping our products. This is one of the key advantages of building an Excel client. Not only does it lend itself well for editing tabular data, it also makes it very easy to provide additional analysis of that data. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Excel Document Customization&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I've been building upon the the Visual Studio Solution that we started in the first post on OBA when we built the data service. So just add a new project to the solution (File -&amp;gt; &lt;strong&gt;Add&lt;/strong&gt; -&amp;gt; New Project) and select Office 2007 Excel Workbook which is available in Visual Studio 2008 Professional and higher:&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient1_4.jpg"&gt;&lt;img height="352" alt="OBAExcelClient1" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient1_thumb_1.jpg" width="702" border="0" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;Since we're building a document customization and not an Add-In this means that our code will only run on the specific document as opposed to running in the Excel application over any document that is opened. After we add the project we're asked if we want to import an existing Excel workbook or create a new one. For this example we'll want to create a new one named the same name as our project, NorthwindClientExcel.xlsx. After we specify this, our project is created and the Excel designer opens. &lt;/p&gt;  &lt;p&gt;Next step is to add the data service reference just like we did for the Outlook Add-In. Right-click on the project, select Add Service Reference. Click the Discover button and it should find our ADO.NET data service in the solution called NorthwindDataService. Name the service reference NorthwindService. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Data Binding in Excel&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Now that we have our service reference we can retrieve the list of Order objects that have not been shipped yet and display them in the first sheet of our workbook. But we'll also want to show the Order Details to the shipping department and display the Quantity and Product that should be shipped. We'll do this using an Excel &lt;a href="http://msdn.microsoft.com/en-us/library/7we49he1.aspx" target="_blank"&gt;Action Pane&lt;/a&gt; by setting up a master-detail view of the data. So as the user scrolls through the Order rows, the Action Pane will display the Order Details. The user only needs to make changes to the Order rows itself so this design will work well. &lt;/p&gt;  &lt;p&gt;The magic control we use in Excel to bind data to rows is called the &lt;a href="http://msdn.microsoft.com/en-us/library/2ttzcbhb.aspx" target="_blank"&gt;ListObject&lt;/a&gt;. This object can easily bind to a Winforms BindingSource just like any other Winforms control. So to set up our data source so we can bind to a BindingSource we'll want a BindingList(Of Order) so that list change notifications are communicated to the UI. We'll also need to augment the Order partial class on the client so that property change notifications are also sent. &lt;/p&gt;  &lt;p&gt;So first create a new class named Order and place it in the same Namespace as the NorthwindService service reference we just added. This is where the client proxy objects are generated for us so in order to extend these classes with our own code we just need to get it into the same Namespace. (Here's a Visual Basic tip, you know you've got it right if you see the Order properties and methods in the Declarations drop down above the editor for the Order class.) We need to fire a change notification on all of the properties of our Order so I've placed code to do this in all the xxxChanged() partial methods like so :&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;NorthwindExcelClient.NorthwindService
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.ComponentModel

&lt;span style="color: blue"&gt;Namespace &lt;/span&gt;NorthwindService

    &lt;span style="color: blue"&gt;Partial Public Class &lt;/span&gt;Order
        &lt;span style="color: blue"&gt;Implements &lt;/span&gt;INotifyPropertyChanged

        &lt;span style="color: blue"&gt;Public Event &lt;/span&gt;PropertyChanged(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As Object&lt;/span&gt;, _
                                     &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;PropertyChangedEventArgs) _
                                     &lt;span style="color: blue"&gt;Implements &lt;/span&gt;INotifyPropertyChanged.PropertyChanged

        &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;FirePropertyChanged(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;propertyName &lt;span style="color: blue"&gt;As String&lt;/span&gt;)
            &lt;span style="color: blue"&gt;If &lt;/span&gt;propertyName &amp;lt;&amp;gt; &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;Then
                RaiseEvent &lt;/span&gt;PropertyChanged(&lt;span style="color: blue"&gt;Me&lt;/span&gt;, &lt;span style="color: blue"&gt;New &lt;/span&gt;PropertyChangedEventArgs(propertyName))
            &lt;span style="color: blue"&gt;End If
        End Sub

        Private Sub &lt;/span&gt;OnShippedDateChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;ShippedDate&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnOrderDateChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;OrderDate&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        &lt;/span&gt;&lt;span style="color: green"&gt;'FirePropertyChanged is called from all xxxChanged() partial methods.
        ' I excluded the rest of the code here for clarity....
.&lt;br /&gt;.&lt;br /&gt;.&lt;/span&gt;&lt;span style="color: green"&gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;    End Class&lt;br /&gt;End Namespace&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Next we need to create a BindingList(Of Order). I'm going to create a class called MyOrdersList that inherits from this which will also encapsulate the calls to the ADO.NET Data Service. MyOrdersList will use the data service context on the client (NorthwindService in our case) to retrieve and update the Orders. We don't want to allow adds or deletes in this application because orders are going through a workflow and our shipping department is only updating the information on an order, specifically the ShippedDate. So we'll need to override AddNewCore and RemoveItem to prevent this. We'll also override the OnListChanged so that we can tell the data service context to mark the Order entity as updated. &lt;/p&gt;

&lt;p&gt;We also need a couple housekeeping fields for saving and for exposing a HasChanges property. The interesting code to notice here is that we're specifying a MergeOption on the data service client to OverwriteChanges after we save as opposed to the default AppendOnly. This means that after we save our changes it will refresh the existing Order entity instances with changes from the database. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;NorthwindExcelClient.NorthwindService
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.ComponentModel

&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;MyOrderList
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;BindingList(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Order)

    &lt;span style="color: blue"&gt;Private &lt;/span&gt;DataServiceContext &lt;span style="color: blue"&gt;As New &lt;/span&gt;NorthwindEntities(&lt;span style="color: blue"&gt;New &lt;/span&gt;Uri(&lt;span style="color: blue"&gt;My&lt;/span&gt;.Settings.ServiceURI))
    &lt;span style="color: blue"&gt;Private &lt;/span&gt;_hasChanges &lt;span style="color: blue"&gt;As Boolean
    Private &lt;/span&gt;_isSaving &lt;span style="color: blue"&gt;As Boolean

    Public ReadOnly Property &lt;/span&gt;HasChanges() &lt;span style="color: blue"&gt;As Boolean
        Get
            Return &lt;/span&gt;_hasChanges
        &lt;span style="color: blue"&gt;End Get
    End Property

    Sub New&lt;/span&gt;()
        &lt;span style="color: blue"&gt;MyBase&lt;/span&gt;.New()
        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.DataServiceContext.MergeOption = Services.Client.MergeOption.OverwriteChanges
    &lt;span style="color: blue"&gt;End Sub

    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Do not allow adds.
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Protected Overrides Function &lt;/span&gt;AddNewCore() &lt;span style="color: blue"&gt;As Object
        Throw New &lt;/span&gt;NotSupportedException(&lt;span style="color: #a31515"&gt;&amp;quot;You cannot add items to the list.&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;Return Nothing
    End Function
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Do not allow deletes.
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param name=&amp;quot;index&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Protected Overrides Sub &lt;/span&gt;RemoveItem(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;index &lt;span style="color: blue"&gt;As Integer&lt;/span&gt;)
        &lt;span style="color: blue"&gt;Throw New &lt;/span&gt;NotSupportedException(&lt;span style="color: #a31515"&gt;&amp;quot;You cannot remove items from the list.&amp;quot;&lt;/span&gt;)
    &lt;span style="color: blue"&gt;End Sub
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' When a property is updated on an order, then we need to
    ''' tell the data services client to mark it as updated.
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param name=&amp;quot;e&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Protected Overrides Sub &lt;/span&gt;OnListChanged(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;System.ComponentModel.ListChangedEventArgs)
        &lt;span style="color: blue"&gt;If Not &lt;/span&gt;_isSaving &lt;span style="color: blue"&gt;Then
            &lt;/span&gt;&lt;span style="color: green"&gt;'The Order partial class is implementing INotifyPropertyChanged so this will work
            &lt;/span&gt;&lt;span style="color: blue"&gt;If &lt;/span&gt;e.ListChangedType = ListChangedType.ItemChanged &lt;span style="color: blue"&gt;Then
                Me&lt;/span&gt;.DataServiceContext.UpdateObject(&lt;span style="color: blue"&gt;Me&lt;/span&gt;(e.NewIndex))
                _hasChanges = &lt;span style="color: blue"&gt;True
            End If
            MyBase&lt;/span&gt;.OnListChanged(e)
        &lt;span style="color: blue"&gt;End If
    End Sub&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Before we get into the code that will retrieve and save the orders, let's bind this to a ListObject and get it onto our Excel worksheet. Since we're going to have to interact with the list of orders from our Sheet1 as well as the &lt;a href="http://msdn.microsoft.com/en-us/library/7we49he1.aspx" target="_blank"&gt;Action Pane&lt;/a&gt; displaying the details, I'm going to create a property on the Workbook itself that exposes the MyOrdersList. Double-click on the ThisWorkbook in the project and switch to the Code view:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;ThisWorkbook

    &lt;span style="color: green"&gt;'This is the data source we'll be working with on the Sheet and Action Pane.
    ' This class communicates with the ADO.NET Data Service
    &lt;/span&gt;&lt;span style="color: blue"&gt;Private &lt;/span&gt;_orderList &lt;span style="color: blue"&gt;As &lt;/span&gt;MyOrderList
    &lt;span style="color: blue"&gt;Public ReadOnly Property &lt;/span&gt;OrderList() &lt;span style="color: blue"&gt;As &lt;/span&gt;MyOrderList
        &lt;span style="color: blue"&gt;Get
            If &lt;/span&gt;_orderList &lt;span style="color: blue"&gt;Is Nothing Then
                &lt;/span&gt;_orderList = &lt;span style="color: blue"&gt;New &lt;/span&gt;MyOrderList()
            &lt;span style="color: blue"&gt;End If
            Return &lt;/span&gt;_orderList
        &lt;span style="color: blue"&gt;End Get
    End Property&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Now build the project and open the Data Sources window.&amp;#160; Add a new Object Data Source and select MyOrderList then Finish. Drag the MyOrderList onto the designer for Sheet1, just drop it into the first cell, and it will generate all the columns for every property on the Order. You can also change the name of it on the Design tab -- I'll change ours to OrderListObject. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient2_4.jpg"&gt;&lt;img height="271" alt="OBAExcelClient2" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient2_thumb_1.jpg" width="709" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Unfortunately it drops all the columns regardless if we select a drop target of none or not. Right click on the column and select Delete from the drop-down menu to delete a column (don't press the delete key). I'm going to remove the first three and the last three columns that it dropped. You'll also want to set any date fields you're displaying in the sheet to Text format. This is to work around a bug in the ListObject where it won't let you change date values if the formatting isn't set to text. You do this by selecting the column then right-click, select Format Cells, and then select Text from the list. &lt;/p&gt;

&lt;p&gt;We can be explicit about setting our data source and binding to columns in the startup event handler:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Sheet1

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;Sheet1_Startup() &lt;span style="color: blue"&gt;Handles Me&lt;/span&gt;.Startup
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;myApp = NorthwindExcelClient.Globals.ThisWorkbook
        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.OrderBindingSource.DataSource = myApp.OrderList

        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.OrderListObject.SetDataBinding(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.OrderBindingSource, &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, _
                                          &lt;span style="color: #a31515"&gt;&amp;quot;ShippedDate&amp;quot;&lt;/span&gt;, _
                                          &lt;span style="color: #a31515"&gt;&amp;quot;Freight&amp;quot;&lt;/span&gt;, _
                                          &lt;span style="color: #a31515"&gt;&amp;quot;ShipName&amp;quot;&lt;/span&gt;, _
                                          &lt;span style="color: #a31515"&gt;&amp;quot;ShipAddress&amp;quot;&lt;/span&gt;, _
                                          &lt;span style="color: #a31515"&gt;&amp;quot;ShipCity&amp;quot;&lt;/span&gt;, _
                                          &lt;span style="color: #a31515"&gt;&amp;quot;ShipRegion&amp;quot;&lt;/span&gt;, _
                                          &lt;span style="color: #a31515"&gt;&amp;quot;ShipPostalCode&amp;quot;&lt;/span&gt;, _
                                          &lt;span style="color: #a31515"&gt;&amp;quot;ShipCountry&amp;quot;&lt;/span&gt;)

        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.OrderListObject.AutoSelectRows = &lt;span style="color: blue"&gt;True

        &lt;/span&gt;myApp.LoadOrders()
    &lt;span style="color: blue"&gt;End Sub&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Also notice the last line calls a method on ThisWorkbook to load the orders. Let's see how we can do this by writing a query against our ADO.NET data service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Querying and Saving Orders via our Data Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we can return back to our MyOrdersList and write a method for returning the list of orders that have not yet been shipped. Here I call the service to return a list of unshipped orders, add them all to MyOrderList and then raise the list changed event once to notify the Excel ListObject to refresh it's UI:&lt;/p&gt;

&lt;pre class="code"&gt; &lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' Queries the open orders from the data service 
''' and returns the number of orders returned in the results
''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;number of orders returned from the service&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/returns&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;Public Function &lt;/span&gt;LoadOrders() &lt;span style="color: blue"&gt;As Integer
    Dim &lt;/span&gt;isLoaded = &lt;span style="color: blue"&gt;True
    Me&lt;/span&gt;.Clear()

    &lt;span style="color: blue"&gt;Me&lt;/span&gt;.RaiseListChangedEvents = &lt;span style="color: blue"&gt;False

    Dim &lt;/span&gt;orders = &lt;span style="color: blue"&gt;From &lt;/span&gt;o &lt;span style="color: blue"&gt;In &lt;/span&gt;DataServiceContext.Orders _
                 &lt;span style="color: blue"&gt;Where &lt;/span&gt;o.ShippedDate &lt;span style="color: blue"&gt;Is Nothing &lt;/span&gt;_
                 &lt;span style="color: blue"&gt;Order By &lt;/span&gt;o.OrderDate

    &lt;span style="color: blue"&gt;For Each &lt;/span&gt;o &lt;span style="color: blue"&gt;In &lt;/span&gt;orders
        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.Add(o)
    &lt;span style="color: blue"&gt;Next

    Me&lt;/span&gt;.RaiseListChangedEvents = &lt;span style="color: blue"&gt;True
    Me&lt;/span&gt;.OnListChanged(&lt;span style="color: blue"&gt;New &lt;/span&gt;ListChangedEventArgs(ListChangedType.Reset, 0))
    &lt;span style="color: blue"&gt;Return Me&lt;/span&gt;.Count
&lt;span style="color: blue"&gt;End Function&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;We're also going to need a way to load the order details, shipper and product entities when requested. This will happen as the user selects rows of data -- we need to display these details in our &lt;a href="http://msdn.microsoft.com/en-us/library/7we49he1.aspx" target="_blank"&gt;Action Pane&lt;/a&gt;. By default these entity references and collections are not loaded, we need to do this explicitly. This is a good thing in our case because it avoids transferring unnecessary data if the user doesn't select the Order row in the sheet. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' Loads the Order Details and Product information from the data 
'''  service and returns the OrderDetails for the specified order.
''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param name=&amp;quot;o&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;Public Sub &lt;/span&gt;LoadOrderDetails(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;o &lt;span style="color: blue"&gt;As &lt;/span&gt;Order)
    &lt;span style="color: blue"&gt;If &lt;/span&gt;(o &lt;span style="color: blue"&gt;IsNot Nothing&lt;/span&gt;) &lt;span style="color: blue"&gt;Then
        If &lt;/span&gt;o.Shipper &lt;span style="color: blue"&gt;Is Nothing Then
            Me&lt;/span&gt;.DataServiceContext.LoadProperty(o, &lt;span style="color: #a31515"&gt;&amp;quot;Shipper&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End If
        If &lt;/span&gt;o.Order_Details &lt;span style="color: blue"&gt;Is Nothing OrElse &lt;/span&gt;o.Order_Details.Count = 0 &lt;span style="color: blue"&gt;Then
            Me&lt;/span&gt;.DataServiceContext.LoadProperty(o, &lt;span style="color: #a31515"&gt;&amp;quot;Order_Details&amp;quot;&lt;/span&gt;)
            &lt;span style="color: blue"&gt;For Each &lt;/span&gt;detail &lt;span style="color: blue"&gt;In &lt;/span&gt;o.Order_Details
                detail.Order = o
                &lt;span style="color: blue"&gt;If &lt;/span&gt;detail.Product &lt;span style="color: blue"&gt;Is Nothing Then
                    Me&lt;/span&gt;.DataServiceContext.LoadProperty(detail, &lt;span style="color: #a31515"&gt;&amp;quot;Product&amp;quot;&lt;/span&gt;)
                &lt;span style="color: blue"&gt;End If
            Next
        End If
    End If
End Sub&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Finally we need a method that submits changes back to the data service. This is easily done by calling SaveChanges on the service context which sends all the changes we made in the client through the service. Note here that we are not sending them in a single batch, therefore if one order fails to update the ones before the failure will still be saved. You may need to put more robust error handling here depending on what kind of failures you anticipate in your applications. Simple error handling is done for this example in the Action Pane (we'll get there next).&lt;/p&gt;

&lt;pre class="code"&gt;    &lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Saves the customer changes back to the service.
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;true if save was successful, otherwise an exception is thrown&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/returns&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Function &lt;/span&gt;SaveChanges() &lt;span style="color: blue"&gt;As Boolean
        Dim &lt;/span&gt;saved &lt;span style="color: blue"&gt;As Boolean
        Try
            &lt;/span&gt;_isSaving = &lt;span style="color: blue"&gt;True
            Me&lt;/span&gt;.DataServiceContext.SaveChanges()
            _hasChanges = &lt;span style="color: blue"&gt;False
            &lt;/span&gt;saved = &lt;span style="color: blue"&gt;True
        Finally
            &lt;/span&gt;_isSaving = &lt;span style="color: blue"&gt;False
        End Try

        Return &lt;/span&gt;saved
    &lt;span style="color: blue"&gt;End Function
&lt;br /&gt;End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Creating the Excel Action Pane Using WPF&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;Now we're ready to design our Action Pane that will display the order details as well as provide a status message area and a Save and Refresh button. Refresh will re-load the orders from the service and Save will send the changes back. (Later we'll also hook up Excel's save button to do the same thing.)&lt;/p&gt;

&lt;p&gt;I've showed how to use WPF in Office applications before when we &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/07/oba-part-2-building-and-outlook-client-against-lob-data.aspx" target="_blank"&gt;built the Outlook Add-In in Part 2.&lt;/a&gt; It's the same technique here -- use the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx" target="_blank"&gt;Winforms ElementHost&lt;/a&gt; as a container for your WPF control. So let's create our WPF user control -- add a new item to the project and select WPF category on the left and then choose WPF User Control. I named it WPFActionPane and click OK. &lt;/p&gt;

&lt;p&gt;The reason for using WPF in this case is so that we could really get a nice look-and-feel that matches Excel's colors. Additionally we can easily provide a couple simple animations so that users notice the control on the right-hand side of the spreadsheet -- this is the default location of an Action Pane. So here's the layout of the control and the styles used to make the read-only GridView have a nice Excel-friendly look:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;UserControl &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Class&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;WPFActionPane&amp;quot;
    &lt;/span&gt;&lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
    &lt;/span&gt;&lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;  
             &lt;/span&gt;&lt;span style="color: red"&gt;MinHeight&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;200&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;MinWidth&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;200&amp;quot; 
             &lt;/span&gt;&lt;span style="color: red"&gt;VerticalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Stretch&amp;quot; 
             &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Stretch&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;400&amp;quot; &amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;UserControl.Resources&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Storyboard &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Key&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;LoadingStoryBoard&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;DoubleAnimation
                    &lt;/span&gt;&lt;span style="color: red"&gt;Storyboard.TargetName&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ListGrid&amp;quot;
                    &lt;/span&gt;&lt;span style="color: red"&gt;Storyboard.TargetProperty&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Opacity&amp;quot;
                    &lt;/span&gt;&lt;span style="color: red"&gt;From&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0.0&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;To&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1.0&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Duration&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0:0:0.5&amp;quot; 
                    &lt;/span&gt;&lt;span style="color: red"&gt;AutoReverse&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;False&amp;quot;  /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Storyboard&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Storyboard &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Key&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;UpdateStoryBoard&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ColorAnimation &lt;/span&gt;&lt;span style="color: red"&gt;From&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;To&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Yellow&amp;quot; 
                    &lt;/span&gt;&lt;span style="color: red"&gt;Storyboard.TargetName&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;txtStatus&amp;quot; 
                    &lt;/span&gt;&lt;span style="color: red"&gt;Storyboard.TargetProperty&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Background.Color&amp;quot; 
                    &lt;/span&gt;&lt;span style="color: red"&gt;AutoReverse&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;True&amp;quot; /&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ColorAnimation &lt;/span&gt;&lt;span style="color: red"&gt;From&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Black&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;To&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; 
                    &lt;/span&gt;&lt;span style="color: red"&gt;Storyboard.TargetName&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;txtStatus&amp;quot; 
                    &lt;/span&gt;&lt;span style="color: red"&gt;Storyboard.TargetProperty&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Foreground.Color&amp;quot; 
                    &lt;/span&gt;&lt;span style="color: red"&gt;AutoReverse&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;True&amp;quot; /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Storyboard&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Style &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Key&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;GridViewStyle&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;TargetType&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;TextBox&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Margin&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;-3,0,-9,-3&amp;quot; /&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Cursor&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Arrow&amp;quot; /&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;IsReadOnly&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;True&amp;quot; /&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;BorderBrush&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#B8CCE4&amp;quot; /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Style&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Style &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Key&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ListViewStyle&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;TargetType&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ListView&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Background&amp;quot;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter.Value&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinearGradientBrush &lt;/span&gt;&lt;span style="color: red"&gt;EndPoint&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0.5,1&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;StartPoint&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0.5,0&amp;quot;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GradientStop &lt;/span&gt;&lt;span style="color: red"&gt;Color&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#4F81BD&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Offset&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0&amp;quot;/&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GradientStop &lt;/span&gt;&lt;span style="color: red"&gt;Color&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Offset&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1.0&amp;quot;/&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinearGradientBrush&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter.Value&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Style&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Style &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Key&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ListViewItemStyle&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;TargetType&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ListViewItem&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Background&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Transparent&amp;quot;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;BorderBrush&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Transparent&amp;quot;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;BorderThickness&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1&amp;quot;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;HorizontalContentAlignment&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Stretch&amp;quot; /&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;VerticalContentAlignment&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Stretch&amp;quot; /&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Height&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;22&amp;quot; /&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;&amp;lt;!--Removes the row higlight--&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Template&amp;quot;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter.Value&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ControlTemplate &lt;/span&gt;&lt;span style="color: red"&gt;TargetType&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Type &lt;/span&gt;&lt;span style="color: red"&gt;ListViewItem&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridViewRowPresenter 
                    &lt;/span&gt;&lt;span style="color: red"&gt;SnapsToDevicePixels&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;SnapsToDevicePixels&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; 
                    &lt;/span&gt;&lt;span style="color: red"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;VerticalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; 
                    &lt;/span&gt;&lt;span style="color: red"&gt;Grid.RowSpan&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;2&amp;quot;/&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ControlTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter.Value&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Style&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Style &lt;/span&gt;&lt;span style="color: red"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: red"&gt;Key&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;GridViewColumnHeaderStyle&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;TargetType&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;GridViewColumnHeader&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Background&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#4F81BD&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Foreground&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#DBE5F1&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;FontWeight&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Bold&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;HorizontalContentAlignment&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Left&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;BorderThickness&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Focusable&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Value&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;False&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;BorderBrush&amp;quot;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter.Value&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinearGradientBrush &lt;/span&gt;&lt;span style="color: red"&gt;EndPoint&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0.5,1&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;StartPoint&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0.5,0&amp;quot;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GradientStop &lt;/span&gt;&lt;span style="color: red"&gt;Color&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Offset&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0&amp;quot;/&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GradientStop &lt;/span&gt;&lt;span style="color: red"&gt;Color&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#B8CCE4&amp;quot;  &lt;/span&gt;&lt;span style="color: red"&gt;Offset&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1.0&amp;quot;/&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinearGradientBrush&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter.Value&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter &lt;/span&gt;&lt;span style="color: red"&gt;Property&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Template&amp;quot;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter.Value&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ControlTemplate &lt;/span&gt;&lt;span style="color: red"&gt;TargetType&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;x&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Type &lt;/span&gt;&lt;span style="color: red"&gt;GridViewColumnHeader&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid &lt;/span&gt;&lt;span style="color: red"&gt;SnapsToDevicePixels&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;True&amp;quot;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Border &lt;/span&gt;&lt;span style="color: red"&gt;BorderThickness&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0,0,0,1&amp;quot; 
                            &lt;/span&gt;&lt;span style="color: red"&gt;BorderBrush&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;Border&lt;/span&gt;&lt;span style="color: blue"&gt;.&lt;/span&gt;&lt;span style="color: red"&gt;BorderBrush&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; 
                            &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;Panel&lt;/span&gt;&lt;span style="color: blue"&gt;.&lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;HeaderBorder&amp;quot;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Border &lt;/span&gt;&lt;span style="color: red"&gt;Padding&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;Control&lt;/span&gt;&lt;span style="color: blue"&gt;.&lt;/span&gt;&lt;span style="color: red"&gt;Padding&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Grid.RowSpan&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;2&amp;quot;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ContentPresenter 
                            &lt;/span&gt;&lt;span style="color: red"&gt;RecognizesAccessKey&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;True&amp;quot; 
                            &lt;/span&gt;&lt;span style="color: red"&gt;Content&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;ContentControl&lt;/span&gt;&lt;span style="color: blue"&gt;.&lt;/span&gt;&lt;span style="color: red"&gt;Content&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; 
                            &lt;/span&gt;&lt;span style="color: red"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;ContentControl&lt;/span&gt;&lt;span style="color: blue"&gt;.&lt;/span&gt;&lt;span style="color: red"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; 
                            &lt;/span&gt;&lt;span style="color: red"&gt;ContentStringFormat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;ContentControl&lt;/span&gt;&lt;span style="color: blue"&gt;.&lt;/span&gt;&lt;span style="color: red"&gt;ContentStringFormat&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; 
                            &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;HeaderContent&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Margin&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0,0,0,1&amp;quot; 
                            &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;Control&lt;/span&gt;&lt;span style="color: blue"&gt;.&lt;/span&gt;&lt;span style="color: red"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; 
                            &lt;/span&gt;&lt;span style="color: red"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;Control&lt;/span&gt;&lt;span style="color: blue"&gt;.&lt;/span&gt;&lt;span style="color: red"&gt;VerticalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; 
                            &lt;/span&gt;&lt;span style="color: red"&gt;SnapsToDevicePixels&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;TemplateBinding &lt;/span&gt;&lt;span style="color: red"&gt;UIElement&lt;/span&gt;&lt;span style="color: blue"&gt;.&lt;/span&gt;&lt;span style="color: red"&gt;SnapsToDevicePixels&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; /&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Border&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Border&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ControlTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter.Value&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Setter&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Style&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;UserControl.Resources&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
 &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Auto&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Auto&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;MainGrid&amp;quot;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RowDefinition &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;50&amp;quot; /&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RowDefinition &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;50&amp;quot; /&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RowDefinition &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;140*&amp;quot; /&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;RowDefinition &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;60&amp;quot; /&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;StackPanel &lt;/span&gt;&lt;span style="color: red"&gt;Orientation&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Horizontal&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Right&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Top&amp;quot;  
                &lt;/span&gt;&lt;span style="color: red"&gt;Visibility&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Hidden&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ButtonStack&amp;quot;&amp;gt;
       &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;40&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;cmdSave&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;40&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Margin&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;3&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;ToolTip&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Save&amp;quot;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Image &lt;/span&gt;&lt;span style="color: red"&gt;Source&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;FloppyDisk.png&amp;quot; /&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;40&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;cmdRefresh&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;40&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Margin&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;3&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;ToolTip&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Refresh&amp;quot;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Image &lt;/span&gt;&lt;span style="color: red"&gt;Source&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Refresh.png&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Image1&amp;quot; /&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Button&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;StackPanel&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;StackPanel &lt;/span&gt;&lt;span style="color: red"&gt;Grid.Row&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;1&amp;quot;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBlock &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;txtShipper&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Auto&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;25&amp;quot;
                 &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;Binding &lt;/span&gt;&lt;span style="color: red"&gt;Path&lt;/span&gt;&lt;span style="color: blue"&gt;=Shipper.CompanyName, &lt;/span&gt;&lt;span style="color: red"&gt;StringFormat&lt;/span&gt;&lt;span style="color: blue"&gt;=Ship &lt;/span&gt;&lt;span style="color: red"&gt;via &lt;/span&gt;\&lt;span style="color: blue"&gt;{&lt;/span&gt;0\&lt;span style="color: blue"&gt;}}&amp;quot;  
                 &lt;/span&gt;&lt;span style="color: red"&gt;Foreground&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;DarkBlue&amp;quot; /&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBlock &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;txtOrderDate&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Auto&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;25&amp;quot;
                  &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;Binding &lt;/span&gt;&lt;span style="color: red"&gt;Path&lt;/span&gt;&lt;span style="color: blue"&gt;=OrderDate, &lt;/span&gt;&lt;span style="color: red"&gt;StringFormat&lt;/span&gt;&lt;span style="color: blue"&gt;=Ordered &lt;/span&gt;\&lt;span style="color: blue"&gt;{&lt;/span&gt;0&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;D&lt;/span&gt;\&lt;span style="color: blue"&gt;}}&amp;quot; 
                  &lt;/span&gt;&lt;span style="color: red"&gt;Foreground&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;DarkBlue&amp;quot;/&amp;gt;
       
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;StackPanel&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Image &lt;/span&gt;&lt;span style="color: red"&gt;Grid.Row&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;2&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Source&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;northwindlogo.gif&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;140&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;140&amp;quot; /&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid &lt;/span&gt;&lt;span style="color: red"&gt;Grid.Row&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;2&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;White&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ListGrid&amp;quot;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ListView 
            &lt;/span&gt;&lt;span style="color: red"&gt;ItemsSource&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;Binding &lt;/span&gt;&lt;span style="color: red"&gt;Path&lt;/span&gt;&lt;span style="color: blue"&gt;=Order_Details}&amp;quot;
            &lt;/span&gt;&lt;span style="color: red"&gt;Style&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;StaticResource &lt;/span&gt;&lt;span style="color: red"&gt;ListViewStyle&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot;
            &lt;/span&gt;&lt;span style="color: red"&gt;ItemContainerStyle&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;StaticResource &lt;/span&gt;&lt;span style="color: red"&gt;ListViewItemStyle&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot;
            &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ListView1&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Margin&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;4&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;IsEnabled&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;True&amp;quot; 
            &lt;/span&gt;&lt;span style="color: red"&gt;BorderThickness&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0&amp;quot; &amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ListView.View&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                 &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridView 
                     &lt;/span&gt;&lt;span style="color: red"&gt;ColumnHeaderContainerStyle&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;StaticResource &lt;/span&gt;&lt;span style="color: red"&gt;GridViewColumnHeaderStyle&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridViewColumn &lt;/span&gt;&lt;span style="color: red"&gt;Header&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Product&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;150&amp;quot;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridViewColumn.CellTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox 
                                    &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;Binding &lt;/span&gt;&lt;span style="color: red"&gt;Path&lt;/span&gt;&lt;span style="color: blue"&gt;=Product.ProductName}&amp;quot; 
                                    &lt;/span&gt;&lt;span style="color: red"&gt;Style&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;StaticResource &lt;/span&gt;&lt;span style="color: red"&gt;GridViewStyle&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot;/&amp;gt;
                            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridViewColumn.CellTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridViewColumn&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridViewColumn &lt;/span&gt;&lt;span style="color: red"&gt;Header&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Quantity&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;61&amp;quot;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridViewColumn.CellTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox 
                                    &lt;/span&gt;&lt;span style="color: red"&gt;Text&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;Binding &lt;/span&gt;&lt;span style="color: red"&gt;Path&lt;/span&gt;&lt;span style="color: blue"&gt;=Quantity, &lt;/span&gt;&lt;span style="color: red"&gt;StringFormat&lt;/span&gt;&lt;span style="color: blue"&gt;='n0'}&amp;quot; 
                                    &lt;/span&gt;&lt;span style="color: red"&gt;Style&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color: #a31515"&gt;StaticResource &lt;/span&gt;&lt;span style="color: red"&gt;GridViewStyle&lt;/span&gt;&lt;span style="color: blue"&gt;}&amp;quot; /&amp;gt;
                            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridViewColumn.CellTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridViewColumn&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;GridView&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ListView.View&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt; 
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ListView&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
   &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid &lt;/span&gt;&lt;span style="color: red"&gt;Grid.Row&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;3&amp;quot;&amp;gt;
       &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;txtStatus&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;TextWrapping&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Wrap&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Background&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Transparent&amp;quot;
              &lt;/span&gt;&lt;span style="color: red"&gt;IsReadOnly&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;True&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;BorderThickness&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;0&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Stretch&amp;quot; 
              &lt;/span&gt;&lt;span style="color: red"&gt;VerticalScrollBarVisibility&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Auto&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Cursor&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Arrow&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
     
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Grid&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;UserControl&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The code that calls the load and save on the orders will be here since this control will interact directly with the list of Orders. In the code-behind of the WPFActionPane we'll also animate the control by running the StoryBoards defined in the XAML when we display the order details and when we display status messages at the bottom of the pane. (Note that I've also included the images referred by the XAML above into the project and &lt;a href="http://msdn.microsoft.com/en-us/library/cc165603.aspx" target="_blank"&gt;set their Build Action to Resource&lt;/a&gt; in the properties for the files in the Solution Explorer). &lt;/p&gt;

&lt;p&gt;We will pass the reference to the list of Orders into the control which we can then set as the DataContext. This will trigger all the data bindings to hook up to the currently selected Order's details as noted by the dot syntax in the bindings above. For instance, if we want to display the shipper's company name then we specify the Shipper.CompanyName path on the Order object contained in the list. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;NorthwindExcelClient.NorthwindService
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Windows.Data
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Windows.Media

&lt;span style="color: blue"&gt;Partial Public Class &lt;/span&gt;WPFActionPane

    &lt;span style="color: blue"&gt;Private &lt;/span&gt;_orderList &lt;span style="color: blue"&gt;As &lt;/span&gt;MyOrderList
    &lt;span style="color: blue"&gt;Public Property &lt;/span&gt;OrderList() &lt;span style="color: blue"&gt;As &lt;/span&gt;MyOrderList
        &lt;span style="color: blue"&gt;Get
            Return &lt;/span&gt;_orderList
        &lt;span style="color: blue"&gt;End Get
        Set&lt;/span&gt;(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;value &lt;span style="color: blue"&gt;As &lt;/span&gt;MyOrderList)
            _orderList = value
            &lt;span style="color: blue"&gt;Me&lt;/span&gt;.DataContext = _orderList
        &lt;span style="color: blue"&gt;End Set
    End Property

    Private Sub &lt;/span&gt;cmdRefresh_Click() &lt;span style="color: blue"&gt;Handles &lt;/span&gt;cmdRefresh.Click
        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.LoadOrders()
    &lt;span style="color: blue"&gt;End Sub

    Private Sub &lt;/span&gt;cmdSave_Click() &lt;span style="color: blue"&gt;Handles &lt;/span&gt;cmdSave.Click
        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.SaveOrders()
    &lt;span style="color: blue"&gt;End Sub
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Saves changes made to the orders in the sheet
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Function &lt;/span&gt;SaveOrders() &lt;span style="color: blue"&gt;As Boolean
        Dim &lt;/span&gt;msg = &lt;span style="color: #a31515"&gt;&amp;quot;Orders could not be saved.&amp;quot; &lt;/span&gt;&amp;amp; vbCrLf
        &lt;span style="color: blue"&gt;Try
            &lt;/span&gt;&lt;span style="color: green"&gt;'Save changes back to the data service
            &lt;/span&gt;&lt;span style="color: blue"&gt;If Me&lt;/span&gt;.OrderList.SaveChanges() &lt;span style="color: blue"&gt;Then
                &lt;/span&gt;msg = &lt;span style="color: #a31515"&gt;&amp;quot;Orders saved.&amp;quot;
            &lt;/span&gt;&lt;span style="color: blue"&gt;End If

            Me&lt;/span&gt;.SetMessage(msg)

        &lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            &lt;span style="color: blue"&gt;Me&lt;/span&gt;.SetMessage(ex.ToString())
        &lt;span style="color: blue"&gt;End Try
    End Function
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Re-loads the orders that are not shipped yet. 
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Sub &lt;/span&gt;LoadOrders()
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;msg = &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;
        &lt;/span&gt;&lt;span style="color: blue"&gt;Try
            Dim &lt;/span&gt;count = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.OrderList.LoadOrders()
            msg = &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;{0} orders returned.&amp;quot;&lt;/span&gt;, count)

            &lt;span style="color: blue"&gt;Me&lt;/span&gt;.SetMessage(msg)
            &lt;span style="color: blue"&gt;Me&lt;/span&gt;.ButtonStack.Visibility = Windows.Visibility.Visible
        &lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            &lt;span style="color: blue"&gt;Me&lt;/span&gt;.SetMessage(ex.ToString())
        &lt;span style="color: blue"&gt;End Try
    End Sub
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Show the Order Details in the ListView by moving the position
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param name=&amp;quot;o&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Sub &lt;/span&gt;DisplayOrderDetails(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;o &lt;span style="color: blue"&gt;As &lt;/span&gt;Order)
        &lt;span style="color: blue"&gt;If &lt;/span&gt;o &lt;span style="color: blue"&gt;IsNot Nothing Then
            Me&lt;/span&gt;.OrderList.LoadOrderDetails(o)
            &lt;span style="color: blue"&gt;Dim &lt;/span&gt;view = CollectionViewSource.GetDefaultView(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.DataContext)
            view.MoveCurrentTo(o)

            &lt;span style="color: blue"&gt;Me&lt;/span&gt;.ListGrid.Visibility = Windows.Visibility.Visible
            &lt;span style="color: blue"&gt;Me&lt;/span&gt;.ListView1.SelectedIndex = -1
            &lt;span style="color: blue"&gt;Dim &lt;/span&gt;story = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.Resources(&lt;span style="color: #a31515"&gt;&amp;quot;LoadingStoryBoard&amp;quot;&lt;/span&gt;), Animation.Storyboard)
            story.Begin()
        &lt;span style="color: blue"&gt;End If
    End Sub
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Sets the status message on the control
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param name=&amp;quot;msg&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Sub &lt;/span&gt;SetMessage(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;msg &lt;span style="color: blue"&gt;As String&lt;/span&gt;)
        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.txtStatus.Text = msg
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;story = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.Resources(&lt;span style="color: #a31515"&gt;&amp;quot;UpdateStoryBoard&amp;quot;&lt;/span&gt;), Animation.Storyboard)
        story.Begin()
    &lt;span style="color: blue"&gt;End Sub

End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now we can create the Action Pane. Add a new item to the project and select Actions Pane Control from the Office group. I named it OrdersActionPane:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient3_2.jpg"&gt;&lt;img height="352" alt="OBAExcelClient3" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient3_thumb.jpg" width="587" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now from the toolbox in the WPF Interoperability category you should see the ElementHost, drag that onto the Actions Pane user control, click the smart tag and select the WPFActionPane control as the hosted content and dock it in the parent container. I'm also going to set the font of the OrdersActionPane to Calibri 11 point. &lt;/p&gt;

&lt;p&gt;In the code behind for the OrdersActionPane we need to set the OrderList for the WPF control as well as listen to position changed event on the OrderListBindingSource that is hooked up as the DataSource of the ListObject on Sheet1. When the position changes we need to tell the WPF control to display that Order's details. There are many ways to integrate WPF and Windows Forms to manage currency but we're trying to keep this example straightforward so we'll do it the easy way:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Data.Services.Client
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;NorthwindExcelClient.NorthwindService

&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;OrdersActionsPane

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;OrdersActionsPane_Load() &lt;span style="color: blue"&gt;Handles Me&lt;/span&gt;.Load
        &lt;span style="color: green"&gt;'Pass in our data source to the WPF control
        &lt;/span&gt;&lt;span style="color: blue"&gt;Me&lt;/span&gt;.WpfActionPane1.OrderList = NorthwindExcelClient.Globals.ThisWorkbook.OrderList
        &lt;span style="color: green"&gt;'When the position changes in the spreadsheet, display the order details in the WPF control
        &lt;/span&gt;&lt;span style="color: blue"&gt;AddHandler &lt;/span&gt;NorthwindExcelClient.Globals.Sheet1.MyOrderListBindingSource.PositionChanged, _
                  &lt;span style="color: blue"&gt;AddressOf Me&lt;/span&gt;.DisplayOrderDetails
    &lt;span style="color: blue"&gt;End Sub

    Private Sub &lt;/span&gt;DisplayOrderDetails(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As Object&lt;/span&gt;, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;EventArgs)
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;source = &lt;span style="color: blue"&gt;TryCast&lt;/span&gt;(sender, BindingSource)
        &lt;span style="color: blue"&gt;If &lt;/span&gt;source &lt;span style="color: blue"&gt;IsNot Nothing Then
            If &lt;/span&gt;source.Position &amp;gt; -1 &lt;span style="color: blue"&gt;Then
                Me&lt;/span&gt;.WpfActionPane1.DisplayOrderDetails(&lt;span style="color: blue"&gt;TryCast&lt;/span&gt;(source.Current, Order))
            &lt;span style="color: blue"&gt;End If
        End If
    End Sub
&lt;/span&gt;&lt;span style="color: blue"&gt;End Class&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Finally we're almost ready to test this out. The last thing we need to do is load the Actions Pane when the application starts as well as expose a LoadOrders to our Sheet. This is because if we're adding charts, pivot tables or other types of controls for data analysis we can't rely on the Action Pane loading the data, we need the sheet to be able to call upon it explicitly. We also will hook up the Excel BeforeSave event so that we can call save on the orders. So back in the ThisWorkbook class:&lt;/p&gt;

&lt;pre class="code"&gt;   &lt;span style="color: blue"&gt;Private &lt;/span&gt;_orderActions &lt;span style="color: blue"&gt;As New &lt;/span&gt;OrdersActionsPane

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;ThisWorkbook_Startup(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As Object&lt;/span&gt;, _
                                     &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;System.EventArgs) &lt;span style="color: blue"&gt;Handles Me&lt;/span&gt;.Startup
        &lt;span style="color: green"&gt;'Load the action pane
        &lt;/span&gt;&lt;span style="color: blue"&gt;Me&lt;/span&gt;.ActionsPane.Controls.Add(_orderActions)
    &lt;span style="color: blue"&gt;End Sub

    Public Sub &lt;/span&gt;LoadOrders()
        _orderActions.WpfActionPane1.LoadOrders()
    &lt;span style="color: blue"&gt;End Sub

    Private Sub &lt;/span&gt;ThisWorkbook_BeforeSave(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;SaveAsUI &lt;span style="color: blue"&gt;As Boolean&lt;/span&gt;, _
                                        &lt;span style="color: blue"&gt;ByRef &lt;/span&gt;Cancel &lt;span style="color: blue"&gt;As Boolean&lt;/span&gt;) &lt;span style="color: blue"&gt;Handles Me&lt;/span&gt;.BeforeSave
        _orderActions.WpfActionPane1.SaveOrders()
    &lt;span style="color: blue"&gt;End Sub
End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Hit F5 and try it out. You will see all the Orders that have not shipped. As you select a row, the details are displayed in the Action Pane and an animation that shows the Northwind logo fades into and out of view so that it catches the user's attention without annoying them ;-). Modify any of the fields in the Sheet and click save to save your changes back to the service. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding a Pivot Table and Chart&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The final thing we want to do is add a pivot table and a pie chart to our Sheet that will display a breakdown of cities we're shipping to. In the designer for Sheet1 select the first cell and then go to the Insert tab. On the left select the arrow under the PivotTable and select PivotChart. A dialog will open which allows you to select the location of the PivotChart. Here I'm just adding it under the ListObject, it will automatically move down as orders come back from the data service. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient4_2.jpg"&gt;&lt;img height="290" alt="OBAExcelClient4" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient4_thumb.jpg" width="606" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now you move into specifying the PivotTable fields and values through Excel like you normally would. Here I'm adding the ShipCity as both a label and a value, which automatically assumes a count. I also right-click on the chart and am allowed to change the chart type to a Pie Chart:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient5_2.jpg"&gt;&lt;img height="393" alt="OBAExcelClient5" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient5_thumb.jpg" width="606" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We're not quite done though. In order to get our PivotTable to update when the data is retrieved from the service we need to add some code to handle this. First name the PivotTable by right-clicking on it and selecting PivotTable Options -- I named it PivotTableShipCity. Now in the code behind we can handle the ListChanged event on the BindingSource which bubbles up what we're doing in our MyOrdersList class -- when we load the orders in the LoadOrders method, we raise the ListChangedEvent and pass a &amp;quot;Reset&amp;quot; parameter. Now we can check that here:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;MyOrderListBindingSource_ListChanged(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As Object&lt;/span&gt;, _
            &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;System.ComponentModel.ListChangedEventArgs) _
            &lt;span style="color: blue"&gt;Handles &lt;/span&gt;MyOrderListBindingSource.ListChanged

    &lt;span style="color: blue"&gt;If &lt;/span&gt;e.ListChangedType = System.ComponentModel.ListChangedType.Reset &lt;span style="color: blue"&gt;Then

        Dim &lt;/span&gt;table = &lt;span style="color: blue"&gt;TryCast&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.PivotTables(&lt;span style="color: #a31515"&gt;&amp;quot;PivotTableShipCity&amp;quot;&lt;/span&gt;), Excel.PivotTable)
        &lt;span style="color: blue"&gt;If &lt;/span&gt;table &lt;span style="color: blue"&gt;IsNot Nothing Then
            &lt;/span&gt;table.RefreshTable()
        &lt;span style="color: blue"&gt;End If
        Me&lt;/span&gt;.MyOrderListBindingSource.MoveFirst()

    &lt;span style="color: blue"&gt;End If
End Sub&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Now when we hit F5 we will see the open orders come down into the spreadsheet and the pie chart will update to display our Excel data visualization. Nice!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient6_2.jpg"&gt;&lt;img height="489" alt="OBAExcelClient6" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart4BuildinganExcelClientagainstLOBD_E5CD/OBAExcelClient6_thumb.jpg" width="664" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;I've updated &lt;a href="http://code.msdn.microsoft.com/OBANorthwind" target="_blank"&gt;our sample on Code Gallery&lt;/a&gt; with a new release that includes this Excel client so have a look. &lt;/p&gt;

&lt;p&gt;Now that we understand what our shipping department is doing we can build out our SharePoint workflow. It will need to parse the purchase order using the &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/12/oba-part-3-storing-and-reading-data-in-word-documents.aspx" target="_blank"&gt;code from part 3&lt;/a&gt; and it will also need to update the order status based on the change made here to the ShippedDate field. We don't want our Excel client to be tightly coupled to SharePoint so we'll need to think about how we can achieve this all from our SharePoint Workflow. Until next time...&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9466700" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Visual+Basic/default.aspx">Visual Basic</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Office/default.aspx">Office</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/OBA/default.aspx">OBA</category></item><item><title>OBA Part 3 - Storing and Reading Data in Word Documents</title><link>http://blogs.msdn.com/bethmassi/archive/2009/02/12/oba-part-3-storing-and-reading-data-in-word-documents.aspx</link><pubDate>Fri, 13 Feb 2009 04:55:33 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9416665</guid><dc:creator>Beth Massi</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9416665.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9416665</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9416665</wfw:comment><description>&lt;p&gt;In my last few posts we've been building a simple Office Business Application (OBA) for the new Northwind Traders. If you missed them:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx" target="_blank"&gt;OBA Part 1 - Exposing Line-of-Business Data&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/07/oba-part-2-building-and-outlook-client-against-lob-data.aspx" target="_blank"&gt;OBA Part 2 - Building and Outlook Client against LOB Data&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In this post I'm going to talk about how we can create a purchase order in Word 2007 that contains data about the items being purchased and how we can query that data and place it into our database. We'll use this code as a basis for our SharePoint Workflow which we will build out in the next post. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/WordOBADiagram_2.jpg"&gt;&lt;img style="margin: 0px 10px 0px 0px" height="375" alt="WordOBADiagram" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/WordOBADiagram_thumb.jpg" width="389" align="left" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you recall &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/02/building-an-office-business-application-for-techready-8.aspx" target="_blank"&gt;our architecture diagram of our Northwind Traders OBA&lt;/a&gt; involved our Sales Reps submitting purchase orders as Word 2007 documents up to SharePoint which kicked off a workflow to parse the document and update the database with the order data through our data service.&lt;/p&gt;  &lt;p&gt;This allows us to store the unstructured document on SharePoint and the structured order data in our database. &lt;/p&gt;  &lt;p&gt;However before we build out the SharePoint Workflow we need a clean way to store and then retrieve the structured order data inside the Word 2007 document. Since Word 2007 documents are Open XML we can use the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c6e744e5-36e9-45f5-8d8c-331df206e0d0&amp;amp;DisplayLang=en" target="_blank"&gt;Open XML SDK&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/bb384460.aspx" target="_blank"&gt;LINQ to XML&lt;/a&gt; to easily parse the document. (I've talked about how to &lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/07/30/accessing-openxml-document-parts-with-the-openxml-sdk.aspx" target="_blank"&gt;manipulate documents with Open XML SDK before here&lt;/a&gt;.) &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Content Controls&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;One way to store data in an Word 2007 document is by using content controls. These allow you to define specific data areas/fields in the document which are then bound to XML that is placed inside the document. When users enter data into these areas of the document the data is stored as a CustomXML Part inside the document. You can use &lt;a href="http://msdn.microsoft.com/en-us/library/bb398244.aspx" target="_blank"&gt;Visual Studio to create content controls and map them to XML&lt;/a&gt; or you can use Word itself. There's also a nifty tool called the &lt;a href="http://www.codeplex.com/dbe" target="_blank"&gt;Word 2007 Content Control Toolkit&lt;/a&gt; that makes the mapping more visual. I'd also highly recommend installing the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=46B6BF86-E35D-4870-B214-4D7B72B02BF9&amp;amp;displaylang=en" target="_blank"&gt;VSTO Power Tools&lt;/a&gt; as well which includes &lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/07/29/handy-visual-studio-add-in-to-view-office-2007-files.aspx" target="_blank"&gt;a VS Add-In for manipulating Open XML documents&lt;/a&gt;. This allows you to look inside the document easily to inspect all the parts directly within Visual Studio.&lt;/p&gt;  &lt;p&gt;So the first thing to do is to create a purchase order template and lay out the content controls on the document. We'll create something very simple using Microsoft Word 2007. On the Developer tab you will see the Controls section. There you can choose which types of controls to lay out on the document. Click the properties button to assign a friendly title and tag to the control. Here I've laid out the minimum information we'll need to submit an order to the system:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc1_2.jpg"&gt;&lt;img height="438" alt="wordcc1" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc1_thumb.jpg" width="672" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Users can write anything else around the content controls but the system only cares about capturing the data we've specified. This gives us the ability to store structured and unstructured data completely inside the .docx file. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Creating and Mapping the XML&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Now we are ready to map the values of the content controls to some custom XML. The XML document for our order looks like this. (Note that there are 10 &amp;lt;OrderDetail&amp;gt; elements I just snipped them for brevity):&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;OrderEntry &lt;/span&gt;&lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;urn:microsoft:examples:oba&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CustomerID &lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;OrderDate &lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Shipper &lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;OrderDetails&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;OrderDetail&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ProductName &lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Quantity &lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;OrderDetail&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;&lt;span style="color: blue"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;OrderDetail&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;...&lt;/span&gt;&lt;span style="color: blue"&gt;
  &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;OrderDetails&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;OrderEntry&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Now open up the &lt;a href="http://www.codeplex.com/dbe" target="_blank"&gt;Word 2007 Content Control Toolkit&lt;/a&gt; an open the OrderEntryTemplate.docx. Under Actions select &amp;quot;Create a new Custom XML Part&amp;quot;, switch to edit view, and then paste in the XML:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc2_2.jpg"&gt;&lt;img height="491" alt="wordcc2" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc2_thumb.jpg" width="594" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Next switch to Bind View and then drag the elements onto the content controls on the left. Make sure you select the element first and then drag it.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc3_2.jpg"&gt;&lt;img height="352" alt="wordcc3" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc3_thumb.jpg" width="629" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Once you're done, save the document and then you can open it in Visual Studio if you've loaded the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=46B6BF86-E35D-4870-B214-4D7B72B02BF9&amp;amp;displaylang=en" target="_blank"&gt;VSTO Power Tools&lt;/a&gt;. This will show the Open XML parts of the document and you can expand the customXml folder and see that our XML has been added to the document. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc4_2.jpg"&gt;&lt;img height="379" alt="wordcc4" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc4_thumb.jpg" width="660" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you back into Word and fill out the content controls and then view the document in Visual Studio again, you will see that the item1.xml custom XML part will contain the data we entered. &lt;/p&gt;

&lt;p&gt;Now that we have a purchase order template we can give this to our sales reps who can collaborate with our high volume customers via email to fill it out. They can then submit the purchase orders to a SharePoint list that can run a workflow to extract the order data and update the database through the data service. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using the Open XML SDK to Retrieve the Order Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The easiest way to programmatically manipulate Office 2007 Open XML documents is by using the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c6e744e5-36e9-45f5-8d8c-331df206e0d0&amp;amp;DisplayLang=en" target="_blank"&gt;Open XML SDK&lt;/a&gt;. Once you install it you can then Add Reference to the DocumentFormat.OpenXML assembly. In order to use LINQ to XML you'll also need a reference to System.Core and System.Xml.Linq. These are imported automatically when you create a new project in Visual Studio 2008. You'll also need to &lt;a href="http://msdn.microsoft.com/en-us/library/cc668183.aspx" target="_blank"&gt;add a Service Reference to the ADO.NET Data Service&lt;/a&gt; like &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target="_blank"&gt;I've shown before&lt;/a&gt;. So let's start simple and just create a console application for now called NorthwindOrderDocParser. Later we'll talk about moving this to a SharePoint workflow. &lt;/p&gt;

&lt;p&gt;Before we start parsing the document let's create a couple simple classes that store the data we're extracting from our document.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' These classes represents the order data that is inside the Word Document. 
''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;DocumentOrderData

    &lt;span style="color: blue"&gt;Sub New&lt;/span&gt;(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;customerID &lt;span style="color: blue"&gt;As String&lt;/span&gt;, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;orderDate &lt;span style="color: blue"&gt;As Date&lt;/span&gt;, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;shipperName &lt;span style="color: blue"&gt;As String&lt;/span&gt;)
        _CustomerID = customerID
        _OrderDate = orderDate
        _Shipper = shipperName
    &lt;span style="color: blue"&gt;End Sub

    Private &lt;/span&gt;_CustomerID &lt;span style="color: blue"&gt;As String
    Public Property &lt;/span&gt;CustomerID() &lt;span style="color: blue"&gt;As String
        Get
            Return &lt;/span&gt;_CustomerID
        &lt;span style="color: blue"&gt;End Get
        Set&lt;/span&gt;(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;value &lt;span style="color: blue"&gt;As String&lt;/span&gt;)
            _CustomerID = value
        &lt;span style="color: blue"&gt;End Set
    End Property

    Private &lt;/span&gt;_OrderDate &lt;span style="color: blue"&gt;As Date
    Public Property &lt;/span&gt;OrderDate() &lt;span style="color: blue"&gt;As Date
        Get
            Return &lt;/span&gt;_OrderDate
        &lt;span style="color: blue"&gt;End Get
        Set&lt;/span&gt;(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;value &lt;span style="color: blue"&gt;As Date&lt;/span&gt;)
            _OrderDate = value
        &lt;span style="color: blue"&gt;End Set
    End Property

    Private &lt;/span&gt;_Shipper &lt;span style="color: blue"&gt;As String
    Public Property &lt;/span&gt;Shipper() &lt;span style="color: blue"&gt;As String
        Get
            Return &lt;/span&gt;_Shipper
        &lt;span style="color: blue"&gt;End Get
        Set&lt;/span&gt;(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;value &lt;span style="color: blue"&gt;As String&lt;/span&gt;)
            &lt;span style="color: blue"&gt;If &lt;/span&gt;value &lt;span style="color: blue"&gt;Is Nothing OrElse &lt;/span&gt;value.Trim = &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;Then
                &lt;/span&gt;value = &lt;span style="color: #a31515"&gt;&amp;quot;Speedy Express&amp;quot;
            &lt;/span&gt;&lt;span style="color: blue"&gt;End If
            &lt;/span&gt;_Shipper = value
        &lt;span style="color: blue"&gt;End Set
    End Property

    Private &lt;/span&gt;_details &lt;span style="color: blue"&gt;As New &lt;/span&gt;List(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Detail)
    &lt;span style="color: blue"&gt;Public ReadOnly Property &lt;/span&gt;Details() &lt;span style="color: blue"&gt;As &lt;/span&gt;List(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Detail)
        &lt;span style="color: blue"&gt;Get
            Return &lt;/span&gt;_details
        &lt;span style="color: blue"&gt;End Get
    End Property

    Public Class &lt;/span&gt;Detail
        &lt;span style="color: blue"&gt;Sub New&lt;/span&gt;(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;productName &lt;span style="color: blue"&gt;As String&lt;/span&gt;, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;quantity &lt;span style="color: blue"&gt;As Short&lt;/span&gt;)
            _ProductName = productName
            _Quantity = quantity
        &lt;span style="color: blue"&gt;End Sub

        Private &lt;/span&gt;_ProductName &lt;span style="color: blue"&gt;As String
        Public Property &lt;/span&gt;ProductName() &lt;span style="color: blue"&gt;As String
            Get
                Return &lt;/span&gt;_ProductName
            &lt;span style="color: blue"&gt;End Get
            Set&lt;/span&gt;(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;value &lt;span style="color: blue"&gt;As String&lt;/span&gt;)
                _ProductName = value
            &lt;span style="color: blue"&gt;End Set
        End Property

        Private &lt;/span&gt;_Quantity &lt;span style="color: blue"&gt;As Short
        Public Property &lt;/span&gt;Quantity() &lt;span style="color: blue"&gt;As Short
            Get
                Return &lt;/span&gt;_Quantity
            &lt;span style="color: blue"&gt;End Get
            Set&lt;/span&gt;(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;value &lt;span style="color: blue"&gt;As Short&lt;/span&gt;)
                _Quantity = value
            &lt;span style="color: blue"&gt;End Set
        End Property
    End Class
End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Next, let's add a schema for the OrderEntry XML data that is contained in the document. This will give us &lt;a href="http://msdn.microsoft.com/en-us/library/bb531325.aspx" target="_blank"&gt;IntelliSense on our XML&lt;/a&gt; when we're using LINQ to XML. We can just open the document in Visual Studio like before and copy the OrderEntry XML data into the clipboard. Then we can Add a new &lt;a href="http://msdn.microsoft.com/en-us/library/cc442691.aspx" target="_blank"&gt;XML to Schema&lt;/a&gt; Item and paste into the Wizard's dialog box. This will infer the schema and place the XSD file into the project automatically for us. Notice that I specified a namespace on our OrderEntry XML data. We now can import this namespace into our main program along with a few other .NET namespaces we'll need:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;'Reference to our data service and data entities:
&lt;/span&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;NorthwindOrderDocParser.NorthwindService
&lt;span style="color: green"&gt;'Open XML SDK:
&lt;/span&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;DocumentFormat.OpenXml.Packaging
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.IO
&lt;span style="color: green"&gt;'Default XML Namespace:
&lt;/span&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #b96464"&gt;xmlns&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;urn:microsoft:examples:oba&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;We are almost ready to start writing our main program to parse the purchase order. First we need a test document. For this test I filled out the following information in a document called MyTestOrder.docx.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc5_2.jpg"&gt;&lt;img height="540" alt="wordcc5" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc5_thumb.jpg" width="654" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now we can write our main program:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Module &lt;/span&gt;Module1

    &lt;span style="color: blue"&gt;Sub &lt;/span&gt;Main()
        &lt;span style="color: blue"&gt;Try
            Dim &lt;/span&gt;docFile = &lt;span style="color: blue"&gt;My&lt;/span&gt;.Computer.FileSystem.GetFileInfo(&lt;span style="color: #a31515"&gt;&amp;quot;MyTestOrder.docx&amp;quot;&lt;/span&gt;)

            &lt;span style="color: blue"&gt;Dim &lt;/span&gt;docData &lt;span style="color: blue"&gt;As &lt;/span&gt;DocumentOrderData
            &lt;span style="color: blue"&gt;Using &lt;/span&gt;sr = docFile.OpenRead()
                &lt;span style="color: green"&gt;'Attempt to parse the document for order data
                &lt;/span&gt;docData = ParseOrderDocument(sr)
                sr.Close()
            &lt;span style="color: blue"&gt;End Using

            If &lt;/span&gt;docData &lt;span style="color: blue"&gt;IsNot Nothing Then
                Dim &lt;/span&gt;employeeEmail = &lt;span style="color: #a31515"&gt;&amp;quot;sales@nwtraders.com&amp;quot;

                &lt;/span&gt;&lt;span style="color: green"&gt;'Attempt to add the order data through the service
                &lt;/span&gt;AddNewOrder(docData, employeeEmail)
                Console.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Order saved successfully.&amp;quot;&lt;/span&gt;)
            &lt;span style="color: blue"&gt;Else
                &lt;/span&gt;Console.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;No order data was found in the document.&amp;quot;&lt;/span&gt;)
            &lt;span style="color: blue"&gt;End If

        Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            Console.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Order could not be processed.&amp;quot; &lt;/span&gt;&amp;amp; vbCrLf &amp;amp; ex.ToString())
        &lt;span style="color: blue"&gt;End Try

        &lt;/span&gt;Console.ReadLine()
    &lt;span style="color: blue"&gt;End Sub&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The ParseOrderDocument method is going to need to grab the XML data from our Custom XML parts as we iterate over the part collection. It's a collection because there can actually be many Custom XML definitions in our document. In order to make grabbing the XML data from the parts easier let's create an &lt;a href="http://msdn.microsoft.com/en-us/library/bb384936.aspx" target="_blank"&gt;Extension method&lt;/a&gt; that extends the OpenXMLPart type. I like to place Extension methods in a separate file called Extensions.vb:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;DocumentFormat.OpenXml.Packaging
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.IO
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Xml

&lt;span style="color: blue"&gt;Module &lt;/span&gt;Extensions

    &lt;span style="color: green"&gt;' Create an extension method so we can easily access the part XML
    &lt;/span&gt;&amp;lt;System.Runtime.CompilerServices.Extension()&amp;gt; _
    &lt;span style="color: blue"&gt;Function &lt;/span&gt;GetXDocument(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;part &lt;span style="color: blue"&gt;As &lt;/span&gt;OpenXmlPart) &lt;span style="color: blue"&gt;As &lt;/span&gt;XDocument
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;xdoc &lt;span style="color: blue"&gt;As &lt;/span&gt;XDocument

        &lt;span style="color: blue"&gt;Using &lt;/span&gt;sr &lt;span style="color: blue"&gt;As New &lt;/span&gt;StreamReader(part.GetStream())
            xdoc = XDocument.Load(XmlReader.Create(sr))
            sr.Close()
        &lt;span style="color: blue"&gt;End Using

        Return &lt;/span&gt;xdoc
    &lt;span style="color: blue"&gt;End Function
End Module&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now we can go back to our main Module1 and add a the ParseOrderDocument method. Notice that I'm using the Extension method we created in the For Each part... loop to return the custom XML as an XDocument. Then I use the child axis property &amp;lt;OrderEntry&amp;gt; (displayed in IntelliSense as I type the query) to see if the element exists. Also notice that since I imported our XML namespace at the top of the file it will only return an &amp;lt;OrderEntry&amp;gt; element in that namespace. So we're safe not to clash with other custom XML that may be added to the document by other processes.&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' Attempts to parse the word document for order data and returns an order
'''  object with all the required. The document must have a customXML part 
'''  that adheres to the OrderEntry.xsd
''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param name=&amp;quot;docStream&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;The document to parse&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/param&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;The order data contained in the document&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/returns&amp;gt;
&lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;Function &lt;/span&gt;ParseOrderDocument(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;docStream &lt;span style="color: blue"&gt;As &lt;/span&gt;Stream) &lt;span style="color: blue"&gt;As &lt;/span&gt;DocumentOrderData
    &lt;span style="color: blue"&gt;Dim &lt;/span&gt;orderData &lt;span style="color: blue"&gt;As &lt;/span&gt;DocumentOrderData = &lt;span style="color: blue"&gt;Nothing

    Try
        &lt;/span&gt;&lt;span style="color: green"&gt;'Use the Open XML SDK to open the document and access parts easily
        &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;wordDoc = WordprocessingDocument.Open(docStream, &lt;span style="color: blue"&gt;False&lt;/span&gt;)

        &lt;span style="color: blue"&gt;Using &lt;/span&gt;wordDoc
            &lt;span style="color: green"&gt;'Get the main document part (document.xml)
            &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;mainPart = wordDoc.MainDocumentPart
            &lt;span style="color: blue"&gt;Dim &lt;/span&gt;docXML &lt;span style="color: blue"&gt;As &lt;/span&gt;XElement = &lt;span style="color: blue"&gt;Nothing

            &lt;/span&gt;&lt;span style="color: green"&gt;'Find the order data custom XML part
            &lt;/span&gt;&lt;span style="color: blue"&gt;For Each &lt;/span&gt;part &lt;span style="color: blue"&gt;In &lt;/span&gt;mainPart.CustomXmlParts
                docXML = part.GetXDocument.&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;OrderEntry&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.FirstOrDefault()
                &lt;span style="color: blue"&gt;If &lt;/span&gt;docXML &lt;span style="color: blue"&gt;IsNot Nothing Then
                    Exit For
                End If
            Next

            If &lt;/span&gt;docXML &lt;span style="color: blue"&gt;Is Nothing Then
                Throw New &lt;/span&gt;InvalidOperationException(&lt;span style="color: #a31515"&gt;&amp;quot;This document does not contain order entry data.&amp;quot;&lt;/span&gt;)
            &lt;span style="color: blue"&gt;End If

            &lt;/span&gt;&lt;span style="color: green"&gt;'Grab the order data fields from the XML 
            &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;customerID = docXML.&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;CustomerID&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.Value.Trim()
            &lt;span style="color: blue"&gt;Dim &lt;/span&gt;orderDate = docXML.&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;OrderDate&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.Value.Trim()
            &lt;span style="color: blue"&gt;Dim &lt;/span&gt;shipper = docXML.&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;Shipper&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.Value.Trim()

            &lt;span style="color: blue"&gt;If &lt;/span&gt;customerID &amp;lt;&amp;gt; &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;AndAlso &lt;/span&gt;IsDate(orderDate) &lt;span style="color: blue"&gt;Then
                &lt;/span&gt;&lt;span style="color: green"&gt;'Create and fill the DocumentOrderData  
                &lt;/span&gt;orderData = &lt;span style="color: blue"&gt;New &lt;/span&gt;DocumentOrderData(customerID, &lt;span style="color: blue"&gt;CDate&lt;/span&gt;(orderDate), shipper)

                &lt;span style="color: blue"&gt;For Each &lt;/span&gt;item &lt;span style="color: blue"&gt;In &lt;/span&gt;docXML.&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;OrderDetails&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;OrderDetail&lt;span style="color: #6464b9"&gt;&amp;gt;
                    &lt;/span&gt;&lt;span style="color: green"&gt;'Grab order details data fields
                    &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;product = item.&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;ProductName&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.Value.Trim()
                    &lt;span style="color: blue"&gt;Dim &lt;/span&gt;quantity = item.&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;Quantity&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.Value.Trim()

                    &lt;span style="color: blue"&gt;If &lt;/span&gt;product &amp;lt;&amp;gt; &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;AndAlso &lt;/span&gt;IsNumeric(quantity) &lt;span style="color: blue"&gt;Then
                        &lt;/span&gt;&lt;span style="color: green"&gt;'Add a new DocumentOrderData.Detail for each product found
                        &lt;/span&gt;orderData.Details.Add(&lt;span style="color: blue"&gt;New &lt;/span&gt;DocumentOrderData.Detail(product, &lt;span style="color: blue"&gt;CShort&lt;/span&gt;(quantity)))
                    &lt;span style="color: blue"&gt;End If

                Next
            End If
            &lt;/span&gt;wordDoc.Close()
        &lt;span style="color: blue"&gt;End Using

    Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
        &lt;span style="color: blue"&gt;Throw New &lt;/span&gt;InvalidOperationException(&lt;span style="color: #a31515"&gt;&amp;quot;Could not process this document.&amp;quot;&lt;/span&gt;, ex)
    &lt;span style="color: blue"&gt;End Try

    Return &lt;/span&gt;orderData
&lt;span style="color: blue"&gt;End Function&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;Updating the Database through the Data Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that we have our document parsed we're just left with adding the data through our data service.&amp;#160; What we need to do is query the reference data (entities) that we'll need to properly associate on our Order. For instance Order will need a reference to the Customer, the Employee and the Shipper. Then each Order_Detail will need a reference to the Product entity. Notice that we're passing the employee email address into this method so that we can associate the sales rep with the order. &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx" target="_blank"&gt;If you recall we had to add this field&lt;/a&gt; to the Customer and Employee tables in Northwind. (For this test program I'm hard-coding the value but later we'll get this information from the Outlook client when it submits the order to SharePoint.)&lt;/p&gt;

&lt;p&gt;Once we have these entities queried and returned from the service we can link them up properly and add our new Order and Order_Details to the data service. For more information on updating data and setting proper linkage to entities returned from an ADO.NET data service &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/20/ado-net-data-services-enforcing-fk-associations-and-a-fix-for-deleting-entities.aspx" target="_blank"&gt;read this post&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/phaniraj/archive/2008/07/02/working-with-relations-in-ado-net-data-services-beta-1.aspx" target="_blank"&gt;this one&lt;/a&gt;. &lt;/p&gt;

&lt;pre class="code"&gt;    &lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Adds a new order through the ADO.NET Data service and sets up all the required
    ''' associations to related entities.
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param name=&amp;quot;docData&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;The order data&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/param&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param name=&amp;quot;employeeEmail&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;EmailAddress of sales representitve&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/param&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;AddNewOrder(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;docData &lt;span style="color: blue"&gt;As &lt;/span&gt;DocumentOrderData, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;employeeEmail &lt;span style="color: blue"&gt;As String&lt;/span&gt;)

        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;ctx &lt;span style="color: blue"&gt;As New &lt;/span&gt;NorthwindEntities(&lt;span style="color: blue"&gt;New &lt;/span&gt;Uri(&lt;span style="color: #a31515"&gt;&amp;quot;http://localhost:1234/Northwind.svc/&amp;quot;&lt;/span&gt;))
      &lt;span style="color: blue"&gt;  Dim &lt;/span&gt;cust &lt;span style="color: blue"&gt;As &lt;/span&gt;Customer
        &lt;span style="color: blue"&gt;Try
            &lt;/span&gt;&lt;span style="color: green"&gt;'Try to retrieve the customer
            &lt;/span&gt;cust = (&lt;span style="color: blue"&gt;From &lt;/span&gt;c &lt;span style="color: blue"&gt;In &lt;/span&gt;ctx.Customers _
                     &lt;span style="color: blue"&gt;Where &lt;/span&gt;c.CustomerID = docData.CustomerID).FirstOrDefault()

        &lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            &lt;span style="color: blue"&gt;Throw New &lt;/span&gt;InvalidOperationException(&lt;span style="color: #a31515"&gt;&amp;quot;Invalid customer ID.&amp;quot;&lt;/span&gt;)&lt;span style="color: blue"&gt;
        End Try

        If &lt;/span&gt;cust &lt;span style="color: blue"&gt;IsNot Nothing Then

            Dim &lt;/span&gt;ship = (&lt;span style="color: blue"&gt;From &lt;/span&gt;s &lt;span style="color: blue"&gt;In &lt;/span&gt;ctx.Shippers _
                        &lt;span style="color: blue"&gt;Where &lt;/span&gt;s.CompanyName = docData.Shipper).FirstOrDefault()

            &lt;span style="color: green"&gt;'Email Address will come from our Outlook client/sales person 
            &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;emp = (&lt;span style="color: blue"&gt;From &lt;/span&gt;e &lt;span style="color: blue"&gt;In &lt;/span&gt;ctx.Employees _
                       &lt;span style="color: blue"&gt;Where &lt;/span&gt;e.EmailAddress = employeeEmail).FirstOrDefault()

            &lt;span style="color: blue"&gt;Dim &lt;/span&gt;o &lt;span style="color: blue"&gt;As New &lt;/span&gt;Order()

            o.OrderDate = docData.OrderDate
            o.RequiredDate = Now.AddDays(2)
            o.ShipAddress = cust.Address
            o.ShipCity = cust.City
            o.ShipCountry = cust.Country
            o.ShipName = cust.ContactName
            o.ShipPostalCode = cust.PostalCode
            o.ShipRegion = cust.Region
            o.Freight = 25

            ctx.AddToOrders(o)

            o.Customer = cust
            ctx.SetLink(o, &lt;span style="color: #a31515"&gt;&amp;quot;Customer&amp;quot;&lt;/span&gt;, cust)

            &lt;span style="color: blue"&gt;If &lt;/span&gt;ship &lt;span style="color: blue"&gt;IsNot Nothing Then
                &lt;/span&gt;o.Shipper = ship
                ctx.SetLink(o, &lt;span style="color: #a31515"&gt;&amp;quot;Shipper&amp;quot;&lt;/span&gt;, ship)
            &lt;span style="color: blue"&gt;End If

            If &lt;/span&gt;emp &lt;span style="color: blue"&gt;IsNot Nothing Then
                &lt;/span&gt;o.Employee = emp
                ctx.SetLink(o, &lt;span style="color: #a31515"&gt;&amp;quot;Employee&amp;quot;&lt;/span&gt;, emp)
            &lt;span style="color: blue"&gt;End If

            &lt;/span&gt;o.Order_Details = &lt;span style="color: blue"&gt;New &lt;/span&gt;System.Collections.ObjectModel.Collection(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Order_Detail)

            &lt;span style="color: blue"&gt;For Each &lt;/span&gt;item &lt;span style="color: blue"&gt;In &lt;/span&gt;docData.Details
                &lt;span style="color: blue"&gt;Dim &lt;/span&gt;productName = item.ProductName.ToLower()
                &lt;span style="color: blue"&gt;Dim &lt;/span&gt;product = (&lt;span style="color: blue"&gt;From &lt;/span&gt;p &lt;span style="color: blue"&gt;In &lt;/span&gt;ctx.Products _
                               &lt;span style="color: blue"&gt;Where &lt;/span&gt;p.ProductName.ToLower() = productName).FirstOrDefault()

                &lt;span style="color: blue"&gt;If &lt;/span&gt;product &lt;span style="color: blue"&gt;IsNot Nothing Then
                    &lt;/span&gt;&lt;span style="color: green"&gt;'Create a detail for each product being ordered
                    &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;detail &lt;span style="color: blue"&gt;As New &lt;/span&gt;Order_Detail()
                    o.Order_Details.Add(detail)

                    detail.Quantity = item.Quantity
                    detail.UnitPrice = &lt;span style="color: blue"&gt;If&lt;/span&gt;(product.UnitPrice.HasValue, _
                                          product.UnitPrice.Value, 1D)

                    ctx.AddToOrder_Details(detail)

                    detail.Product = product
                    ctx.SetLink(detail, &lt;span style="color: #a31515"&gt;&amp;quot;Product&amp;quot;&lt;/span&gt;, product)

                    detail.Order = o
                    ctx.SetLink(detail, &lt;span style="color: #a31515"&gt;&amp;quot;Order&amp;quot;&lt;/span&gt;, o)

                    ctx.AddLink(o, &lt;span style="color: #a31515"&gt;&amp;quot;Order_Details&amp;quot;&lt;/span&gt;, detail)
                &lt;span style="color: blue"&gt;End If
            Next
            &lt;/span&gt;&lt;span style="color: green"&gt;'Saving in Batch mode will update the data inside a database transaction
            'This will throw an exception if the service can't save the Order
            &lt;/span&gt;ctx.SaveChanges(Services.Client.SaveChangesOptions.Batch)
        &lt;span style="color: blue"&gt;End If
    End Sub
End Module&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;When we run this program we will see that Customer ALFKI now has a new Order and 4 Order Details entered into the database. Since we're sending the updates in Batch mode this will cause our order data to be properly wrapped in a database transaction.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc6_2.jpg"&gt;&lt;img height="509" alt="wordcc6" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart3ReadingDatafromWordDocuments_DE22/wordcc6_thumb.jpg" width="666" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Next post we'll talk about how we can create a SharePoint workflow to run this code when order documents are added to a SharePoint list. However, if SharePoint is not a requirement of your system (maybe you have no need to collaborate on documents or store this unstructured data) you could easily add this code directly to the &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/07/oba-part-2-building-and-outlook-client-against-lob-data.aspx" target="_blank"&gt;Outlook client we built in the previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I updated &lt;a href="http://code.msdn.microsoft.com/OBANorthwind" target="_blank"&gt;the sample on Code Gallery&lt;/a&gt; with this project so have a look. &lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9416665" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Visual+Basic/default.aspx">Visual Basic</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/XML/default.aspx">XML</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Office/default.aspx">Office</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Data/default.aspx">Data</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/OBA/default.aspx">OBA</category></item><item><title>OBA Part 2 - Building an Outlook Client against LOB Data</title><link>http://blogs.msdn.com/bethmassi/archive/2009/02/07/oba-part-2-building-and-outlook-client-against-lob-data.aspx</link><pubDate>Sun, 08 Feb 2009 01:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9405756</guid><dc:creator>Beth Massi</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9405756.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9405756</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9405756</wfw:comment><description>&lt;P&gt;In the last couple posts we've been talking about an &lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/02/02/building-an-office-business-application-for-techready-8.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/02/02/building-an-office-business-application-for-techready-8.aspx"&gt;Office Business Application (OBA) architecture for the new Northwind Traders&lt;/A&gt; and &lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx"&gt;how to expose line-of-business (LOB) data&lt;/A&gt;, in our case the Northwind SQL database, &lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx"&gt;using ADO.NET Data Services&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;&lt;IMG style="MARGIN: 0px 5px 0px 0px" height=352 alt=OutlookOBAdiagram src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookOBAdiagram_thumb_1.jpg" width=178 align=left border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookOBAdiagram_thumb_1.jpg"&gt;Today we're going to talk about how to build an Outlook Add-In that pulls the order history from the database through our data service when a customer email arrives in the inbox of our sales reps. This allows the sales reps to easily communicate current order status and product inventory with the customer without having to open up another program. That's the idea -- we're choosing to build a solution that is instantly familiar to our users since they already live in Outlook. &lt;/P&gt;
&lt;P&gt;We're going to display the order history and inventory information in a WPF control in an adjoining form region so that it displays on the email item itself. It will display when the email opens or is displayed in the preview pane. We could have used a Windows Forms control but WPF is going to look a lot better. We want to match the blue color gradients that Outlook uses so that the control looks built in. Using WPF in Office solutions built with Visual Studio is really easy so let's get started.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The Outlook Add-in Project&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;I'm going to build upon the Visual Studio Solution that we started in the previous post when we built the data service. This solution also contains a database project that I'm using to keep the change scripts organized. If you recall we needed to add an EmailAddress field to Customers and Employees tables in Northwind. We also added some Customer and Employee data that specify the email addresses we are going to use to test the sample.&lt;/P&gt;
&lt;P&gt;So just add a new project to the solution and select Office 2007 Outlook Add-In which is available in Visual Studio 2008 Professional and higher: &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient1_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient1_2.jpg"&gt;&lt;IMG height=368 alt=OutlookClient1 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient1_thumb.jpg" width=691 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient1_thumb.jpg"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Next we need to add a service reference to the data service &lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx"&gt;like I showed here&lt;/A&gt; when building a simple console app client. Right-click on the project, select Add Service Reference, click the "Discover" button and name the reference NorthwindService. This will generate the proxy code and entity types used by the data service. It will also add a reference to the System.Data.Services.Client assembly.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Building the Outlook Form Region&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now we'll add the Outlook Form region. Add new item to the project and select Outlook Form Region and name it EmailForm. When you click "Add", a dialog will appear that will ask you if you want to design a new region yourself or if you want to import one. Select "Design a new form region" and click Next. Then it asks you how you want the region to appear, whether it should be on it's own tab or adjoining or a complete replacement. We want to display the order and product information below the customer emails so select adjoining.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient2_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient2_2.jpg"&gt;&lt;IMG height=300 alt=OutlookClient2 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient2_thumb.jpg" width=345 align=left border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient2_thumb.jpg"&gt;&lt;/A&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient3_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient3_2.jpg"&gt;&lt;IMG height=300 alt=OutlookClient3 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient3_thumb.jpg" width=346 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient3_thumb.jpg"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;When we click next we are asked what the Name of the adjoining region should be -- this is displayed in the separator between the email and our control -- so I have specified "Order History". And since we only want to display order history on emails in read mode, uncheck the compose mode checkbox. Finally we are asked which message classes will display the form region. Keep the default selection which specifies all messages. Click finish and the designer will display an empty Windows Forms user control. &lt;/P&gt;
&lt;P&gt;Let's test this out real quick, even though we haven't written any code. Set the Outlook client as the Startup Project and hit F5 and you will see Outlook open. Select any message in your inbox and notice that below the email you will see a blank form region labeled "Order History". However we don't want the form region to display for every email we get, only the Northwind customers. So what we'll do is write some code that checks the Northwind database for any email addresses coming into the inbox to see if they match our customers and only display the region in that case. Back on the EmailForm user control right-click and view code, you will see the following template already set up for you:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;Microsoft.Office.Tools.Outlook

&lt;SPAN style="COLOR: blue"&gt;Public Class &lt;/SPAN&gt;EmailForm
&lt;SPAN style="COLOR: blue"&gt;#Region &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;"Form Region Factory"
    &lt;/SPAN&gt;&amp;lt;Microsoft.Office.Tools.Outlook.FormRegionMessageClass(FormRegionMessageClassAttribute.Note)&amp;gt; _
    &amp;lt;Microsoft.Office.Tools.Outlook.FormRegionName(&lt;SPAN style="COLOR: #a31515"&gt;"NorthwindOutlookClient.EmailForm"&lt;/SPAN&gt;)&amp;gt; _
    &lt;SPAN style="COLOR: blue"&gt;Partial Public Class &lt;/SPAN&gt;EmailFormFactory

        &lt;SPAN style="COLOR: green"&gt;' Occurs before the form region is initialized.
        ' To prevent the form region from appearing, set e.Cancel to true.
        ' Use e.OutlookItem to get a reference to the current Outlook item.
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;EmailFormFactory_FormRegionInitializing(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;sender &lt;SPAN style="COLOR: blue"&gt;As Object&lt;/SPAN&gt;, _
                                                     &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;e &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;FormRegionInitializingEventArgs) _
                                                     &lt;SPAN style="COLOR: blue"&gt;Handles Me&lt;/SPAN&gt;.FormRegionInitializing
        &lt;SPAN style="COLOR: blue"&gt;End Sub
    End Class
#End Region
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'Occurs before the form region is displayed. 
    'Use Me.OutlookItem to get a reference to the current Outlook item.
    'Use Me.OutlookFormRegion to get a reference to the form region.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;EmailForm_FormRegionShowing(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;sender &lt;SPAN style="COLOR: blue"&gt;As Object&lt;/SPAN&gt;, _
                                      &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;e &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;System.EventArgs) &lt;SPAN style="COLOR: blue"&gt;Handles MyBase&lt;/SPAN&gt;.FormRegionShowing
    &lt;SPAN style="COLOR: blue"&gt;End Sub

    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'Occurs when the form region is closed.   
    'Use Me.OutlookItem to get a reference to the current Outlook item.
    'Use Me.OutlookFormRegion to get a reference to the form region.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;EmailForm_FormRegionClosed(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;sender &lt;SPAN style="COLOR: blue"&gt;As Object&lt;/SPAN&gt;, _
                                     &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;e &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;System.EventArgs) &lt;SPAN style="COLOR: blue"&gt;Handles MyBase&lt;/SPAN&gt;.FormRegionClosed
    &lt;SPAN style="COLOR: blue"&gt;End Sub
End Class&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;The EmailFormFactory nested class is what creates the EmailForm and it gives us a chance to cancel showing the region. Here's where we need to write some code that gets the email address from the mail item and checks the database through the data service. In the FormRegionShowing event handler of the EmailForm we will pull down the Order History based on the customer address along with the Order_Details and related Products. Since we're going to need to get the EmailAddress as well as connect to the same data service in both event handlers, a good place to write global code is in the ThisAddIn class which is automatically created for you when you create the Add-in project. &lt;/P&gt;
&lt;P&gt;Double-click on ThisAddIn in the Solution Explorer to open the code. You will see StartUp and ShutDown event handlers for the Add-In automatically generated for you. We don't need to add any code into these handlers. All we need to do is add a public property to the service reference for our data service as well as a function to extract the SMTP email address from the mail item. Note that I added an application setting to specify the location of the data service. During development this is going to be http://localhost:1234:/Northwind.svc but when we deploy the application we'll change it to the location of our production service:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;NorthwindOutlookClient.NorthwindService

&lt;SPAN style="COLOR: blue"&gt;Public Class &lt;/SPAN&gt;ThisAddIn

    &lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;_ctx &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;NorthwindEntities
    &lt;SPAN style="COLOR: blue"&gt;Public ReadOnly Property &lt;/SPAN&gt;DataServiceContext() &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;NorthwindEntities
        &lt;SPAN style="COLOR: blue"&gt;Get
            If &lt;/SPAN&gt;_ctx &lt;SPAN style="COLOR: blue"&gt;Is Nothing Then
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'Specify the Service URI in the app.config via project settings.
                &lt;/SPAN&gt;_ctx = &lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;NorthwindEntities(&lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;Uri(&lt;SPAN style="COLOR: blue"&gt;My&lt;/SPAN&gt;.Settings.ServiceURI))
            &lt;SPAN style="COLOR: blue"&gt;End If
            Return &lt;/SPAN&gt;_ctx
        &lt;SPAN style="COLOR: blue"&gt;End Get
    End Property

    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;''' &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;''' Extracts the SMTP email address from the mail item.
    ''' &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;''' &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;param name="mailItem"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;the Outlook mail item&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;/param&amp;gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;''' &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;returns&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;The SMTP email address, otherwise empty string&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;/returns&amp;gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;''' &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Public Function &lt;/SPAN&gt;GetEmailAddress(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;mailItem &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Outlook.MailItem) &lt;SPAN style="COLOR: blue"&gt;As String
        Dim &lt;/SPAN&gt;recip &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Outlook.Recipient
        &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;exUser &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Outlook.ExchangeUser
        &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;emailAddress &lt;SPAN style="COLOR: blue"&gt;As String &lt;/SPAN&gt;= &lt;SPAN style="COLOR: #a31515"&gt;""

        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Try
            If &lt;/SPAN&gt;mailItem &lt;SPAN style="COLOR: blue"&gt;IsNot Nothing AndAlso &lt;/SPAN&gt;mailItem.SenderEmailType &lt;SPAN style="COLOR: blue"&gt;IsNot Nothing Then
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;''get SMTP Address for the sender of this email
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;mailItem.SenderEmailType.ToLower = &lt;SPAN style="COLOR: #a31515"&gt;"ex" &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Then
                    &lt;/SPAN&gt;recip = Globals.ThisAddIn.Application.GetNamespace(&lt;SPAN style="COLOR: #a31515"&gt;"MAPI"&lt;/SPAN&gt;) _
                            .CreateRecipient(mailItem.SenderEmailAddress)

                    exUser = recip.AddressEntry.GetExchangeUser()
                    emailAddress = exUser.PrimarySmtpAddress
                &lt;SPAN style="COLOR: blue"&gt;Else
                    &lt;/SPAN&gt;emailAddress = mailItem.SenderEmailAddress
                &lt;SPAN style="COLOR: blue"&gt;End If
            End If

        Catch &lt;/SPAN&gt;ex &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Exception
            emailAddress = &lt;SPAN style="COLOR: #a31515"&gt;""
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;End Try
        Return &lt;/SPAN&gt;emailAddress
    &lt;SPAN style="COLOR: blue"&gt;End Function

    Private Sub &lt;/SPAN&gt;ThisAddIn_Startup(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;sender &lt;SPAN style="COLOR: blue"&gt;As Object&lt;/SPAN&gt;, _
                                  &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;e &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;System.EventArgs) &lt;SPAN style="COLOR: blue"&gt;Handles Me&lt;/SPAN&gt;.Startup
    &lt;SPAN style="COLOR: blue"&gt;End Sub

    Private Sub &lt;/SPAN&gt;ThisAddIn_Shutdown(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;sender &lt;SPAN style="COLOR: blue"&gt;As Object&lt;/SPAN&gt;, _
                                   &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;e &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;System.EventArgs) &lt;SPAN style="COLOR: blue"&gt;Handles Me&lt;/SPAN&gt;.Shutdown
    &lt;SPAN style="COLOR: blue"&gt;End Sub
End Class&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Now back in the EmailFormFactory we can add this code to check if we should even be displaying the form region at all. If we don't want to show it, just set e.Cancel =True:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;' Occurs before the form region is initialized.
' To prevent the form region from appearing, set e.Cancel to true.
' Use e.OutlookItem to get a reference to the current Outlook item.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;EmailFormFactory_FormRegionInitializing(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;sender &lt;SPAN style="COLOR: blue"&gt;As Object&lt;/SPAN&gt;, _
                                                    &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;e &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;FormRegionInitializingEventArgs) _
                                                    &lt;SPAN style="COLOR: blue"&gt;Handles Me&lt;/SPAN&gt;.FormRegionInitializing
    &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;emailAddress &lt;SPAN style="COLOR: blue"&gt;As String &lt;/SPAN&gt;= &lt;SPAN style="COLOR: #a31515"&gt;""
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;ctx = NorthwindOutlookClient.Globals.ThisAddIn.DataServiceContext
    &lt;SPAN style="COLOR: blue"&gt;Try
        Dim &lt;/SPAN&gt;mailItem = &lt;SPAN style="COLOR: blue"&gt;TryCast&lt;/SPAN&gt;(e.OutlookItem, Outlook.MailItem)
        emailAddress = NorthwindOutlookClient.Globals.ThisAddIn.GetEmailAddress(mailItem)

        &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;emailAddress &amp;lt;&amp;gt; &lt;SPAN style="COLOR: #a31515"&gt;"" &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Then
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'Make sure the email address is actually in the database
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;customer = (&lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;c &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;ctx.Customers _
                            &lt;SPAN style="COLOR: blue"&gt;Where &lt;/SPAN&gt;c.EmailAddress = emailAddress).FirstOrDefault()

            &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;customer &lt;SPAN style="COLOR: blue"&gt;Is Nothing Then
                &lt;/SPAN&gt;emailAddress = &lt;SPAN style="COLOR: #a31515"&gt;""
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;End If
        End If
    Catch &lt;/SPAN&gt;ex &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Exception
        &lt;SPAN style="COLOR: green"&gt;'TODO: Error logging
        &lt;/SPAN&gt;emailAddress = &lt;SPAN style="COLOR: #a31515"&gt;""
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;End Try

    &lt;/SPAN&gt;e.Cancel = (emailAddress = &lt;SPAN style="COLOR: #a31515"&gt;""&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Note that a service call could experience unexpected delays depending on where the data service is located. We may want to consider just displaying the form region and writing the calls to the service asynchronously. This is possible using the &lt;A href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc907912.aspx"&gt;ADO.NET Data Services client as described in this article&lt;/A&gt;. For now, we'll keep this OBA sample simple and assume that the data service is located somewhere on our intranet.&lt;/P&gt;
&lt;P&gt;Now that we have this code in place we can write the code that will specify a LINQ query to retrieve the order history in the EmailForm's FormRegionShowing handler. Notice I'm using the ".Expand" syntax in the query to pull in the related entities on the Order. Then I'm pulling the Product entity down for each of the Order_Detail entities so I can display inventory information. (We may want to consider only pulling orders within a date range for better scalability but here I'm pulling all of them down for the specified customer for simplicity.) &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;'Occurs before the form region is displayed. 
'Use Me.OutlookItem to get a reference to the current Outlook item.
'Use Me.OutlookFormRegion to get a reference to the form region.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;EmailForm_FormRegionShowing(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;sender &lt;SPAN style="COLOR: blue"&gt;As Object&lt;/SPAN&gt;, _
                &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;e &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;System.EventArgs) &lt;SPAN style="COLOR: blue"&gt;Handles MyBase&lt;/SPAN&gt;.FormRegionShowing

    &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;emailAddress &lt;SPAN style="COLOR: blue"&gt;As String &lt;/SPAN&gt;= &lt;SPAN style="COLOR: #a31515"&gt;""
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;ctx = NorthwindOutlookClient.Globals.ThisAddIn.DataServiceContext
    &lt;SPAN style="COLOR: blue"&gt;Try
        Dim &lt;/SPAN&gt;mailItem = &lt;SPAN style="COLOR: blue"&gt;TryCast&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.OutlookItem, Outlook.MailItem)
        emailAddress = NorthwindOutlookClient.Globals.ThisAddIn.GetEmailAddress(mailItem)

        &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;emailAddress &amp;lt;&amp;gt; &lt;SPAN style="COLOR: #a31515"&gt;"" &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Then
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'pull the order history from the database
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;customerOrders = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;o &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;ctx.Orders.Expand(&lt;SPAN style="COLOR: #a31515"&gt;"Order_Details"&lt;/SPAN&gt;).Expand(&lt;SPAN style="COLOR: #a31515"&gt;"Customer"&lt;/SPAN&gt;) _
                              &lt;SPAN style="COLOR: blue"&gt;Where &lt;/SPAN&gt;o.Customer.EmailAddress = emailAddress _
                              &lt;SPAN style="COLOR: blue"&gt;Order By &lt;/SPAN&gt;o.OrderDate &lt;SPAN style="COLOR: blue"&gt;Descending

            For Each &lt;/SPAN&gt;order &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;customerOrders
                &lt;SPAN style="COLOR: blue"&gt;For Each &lt;/SPAN&gt;detail &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;order.Order_Details
                    ctx.LoadProperty(detail, &lt;SPAN style="COLOR: #a31515"&gt;"Product"&lt;/SPAN&gt;)
                &lt;SPAN style="COLOR: blue"&gt;Next
            Next

            Dim &lt;/SPAN&gt;ordersList &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;List(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Order)(customerOrders)
            &lt;SPAN style="COLOR: green"&gt;'TODO: Set this ordersList as the DataContext of our WPF user control

        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;End If
    Catch &lt;/SPAN&gt;ex &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Exception
        &lt;SPAN style="COLOR: green"&gt;'Could not connect to the service
        'TODO: Error logging
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;End Try
End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;You also should notice that we still need to pass this list of Order entities that were returned from the data service into our WPF control -- but first we need to create it!&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Building the WPF User Control&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;So let's add a new WPF User control via Add New Item (listed under WPF) -- I named it OrderHistory. This will show the WPF designer. The WPF User Control simply specifies just the UI in XAML of what the control should look like and sets up the data binding to the properties on our entities. &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient4_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient4_2.jpg"&gt;&lt;IMG height=352 alt=OutlookClient4 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient4_thumb.jpg" width=636 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient4_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Here we've set up two ListViews that display Order and Order_Details and below that the Product inventory information along with an &lt;A class="" href="http://msdn.microsoft.com/en-us/library/cc165603.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc165603.aspx"&gt;Image Control&lt;/A&gt; showing off the new Northwind logo. This control is really easy to data bind because of how the entity associations are specified in our data model. Order has Order_Details collection and Order_Detail has a Product reference. When the WPF User Control's DataContext property is set to the list of Orders, the data binding will take care of displaying the related data properly. Here's how we set up the data bound controls (styles omitted for clarity):&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;UserControl &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Class&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="OrderHistory"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="300" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="541" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="OrderList" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.IsSharedSizeScope&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="True"&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;UserControl.Resources&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Style ...&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #a31515"&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;UserControl.Resources&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.RowDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;RowDefinition &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="120" /&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;RowDefinition &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="160*" /&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.RowDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
       
&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;IsSynchronizedWithCurrentItem&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="True" 
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ItemsSource&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;}" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="ListViewOrder" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,0,6" 
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Style&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StaticResource &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ListViewStyle&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;}"&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView.View&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridView &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ColumnHeaderContainerStyle&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StaticResource &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ColumnHeaderStyle&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;}"&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;=ShipName}&lt;/STRONG&gt;" 
                            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="200"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Ship to&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=OrderDate, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;='d'}&lt;/STRONG&gt;" 
                            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="100"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Order Date&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=ShippedDate, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;='d'}&lt;/STRONG&gt;" 
                            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="100"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Ship Date&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=OrderTotal, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;='c2'}&lt;/STRONG&gt;" 
                            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="100"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Order Total&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridView&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView.View&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Row&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="DetailsGrid" &lt;BR&gt;          &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;DataContext&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;=Order_Details}"&lt;/STRONG&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;ItemsSource&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;}"&lt;/STRONG&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Style&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StaticResource &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ListViewStyle&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;}"
                  &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;IsSynchronizedWithCurrentItem&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="True" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="ListViewDetails" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,0,81"&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView.View&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
                &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridView &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ColumnHeaderContainerStyle&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StaticResource &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ColumnHeaderStyle&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;}"&amp;gt;
                    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Header&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Product" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="300" 
                                    &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;=Product.ProductName}"&lt;/STRONG&gt; /&amp;gt;
                    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Header&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Quantity" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="100" 
                                    &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=Quantity, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;='n0'}&lt;/STRONG&gt;" /&amp;gt;
                    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Header&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Unit Price" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="100" 
                                    &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=UnitPrice, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;='c2'}&lt;/STRONG&gt;" /&amp;gt;
                &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridView&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView.View&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="75" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Image1" 
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Stretch&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="None" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Bottom" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="75" 
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Source&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="northwindlogo75.gif" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;SnapsToDevicePixels&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="True" 
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StretchDirection&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="DownOnly" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;MinHeight&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="75" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;MinWidth&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="75" 
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;MaxHeight&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="75" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;MaxWidth&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="75" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ClipToBounds&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="True" /&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="75" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="StackPanel1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Bottom" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,81,0"&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBlock &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="txtProductName" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto"
                       &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;=Product.ProductName, 
                                      &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=Inventory &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;information for &lt;/SPAN&gt;\&lt;SPAN style="COLOR: blue"&gt;{&lt;/SPAN&gt;0\&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;}}" &lt;/STRONG&gt;/&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBlock &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="txtUnitsInStock" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto" 
                       &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;=Product.UnitsInStock, 
                                      &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=Units &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;in stock&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;: &lt;/SPAN&gt;\&lt;SPAN style="COLOR: blue"&gt;{&lt;/SPAN&gt;0&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;n0&lt;/SPAN&gt;\&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;}}"&lt;/STRONG&gt; /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBlock &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="txtUnitsOnOrder" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto" 
                       &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: red"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;=Product.UnitsOnOrder, 
                                      &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=Units &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;on order&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;: &lt;/SPAN&gt;\&lt;SPAN style="COLOR: blue"&gt;{&lt;/SPAN&gt;0&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;n0&lt;/SPAN&gt;\&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;}}&lt;/STRONG&gt;"/&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;UserControl&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Notice that there is a field I'm binding to called OrderTotal on the Order entity however if you go back to the data model (Northwind.edmx in the NorthwindService project) you won't see this field coming from the database. That's because it's a calculated property on the Order entity on the client. You can extend the entities on the client using Partial Classes. All you have to do is right click on the project and select Add--&amp;gt;Class, call it Order, and then make sure you specify the proper namespace of the service reference:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;NorthwindOutlookClient.NorthwindService

&lt;SPAN style="COLOR: blue"&gt;Namespace &lt;/SPAN&gt;NorthwindService

    &lt;SPAN style="COLOR: blue"&gt;Partial Public Class &lt;/SPAN&gt;Order

        &lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;_total &lt;SPAN style="COLOR: blue"&gt;As Decimal &lt;/SPAN&gt;= 0
        &lt;SPAN style="COLOR: blue"&gt;Public ReadOnly Property &lt;/SPAN&gt;OrderTotal() &lt;SPAN style="COLOR: blue"&gt;As Decimal
            Get
                If &lt;/SPAN&gt;_total = 0 &lt;SPAN style="COLOR: blue"&gt;Then&lt;/SPAN&gt;
                    _total = &lt;SPAN style="COLOR: blue"&gt;Aggregate&lt;/SPAN&gt; detail &lt;SPAN style="COLOR: blue"&gt;In Me&lt;/SPAN&gt;.Order_Details _
                                &lt;SPAN style="COLOR: blue"&gt;Into&lt;/SPAN&gt; Sum(detail.Quantity * detail.UnitPrice)&lt;SPAN style="COLOR: blue"&gt;                    
                End If
                Return &lt;/SPAN&gt;_total
            &lt;SPAN style="COLOR: blue"&gt;End Get
        End Property
    End Class

End Namespace&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Now that we have our WPF control all designed we are ready to add it to our form region. EmailForm is a Windows Forms user control so in order to add the WPF user control we need to first add an ElementHost control. This is found in the WPF Interoperability Tab on your toolbox. When you drop this control onto the designer you can immediately select the WPF user control to display, in our case it shows the OrderHistory control we just designed (if you don't see it, build the project first).&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient5_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient5_2.jpg"&gt;&lt;IMG height=338 alt=OutlookClient5 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient5_thumb.jpg" width=709 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient5_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I also set it to dock in the parent container so it takes up the entire region and set the font of the EmailForm region to Calibri 11. Lastly we can add the line of code back in our EmailForm_FormRegionShowing handler to set the list of Orders we returned from our data service to the DataContext of the WPF user control:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;ordersList &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;List(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Order)(customerOrders)
&lt;SPAN style="COLOR: green"&gt;'Set this ordersList as the DataContext of our WPF user control
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.OrderHistory1.DataContext = ordersList&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;That should do it! To test this you need to make sure the email address you'll be using is in the database so you'll have to add some test data. When we run it we should see the adjoining form region at the bottom of our customer emails (click to enlarge):&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient6_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient6_2.jpg"&gt;&lt;IMG height=444 alt=OutlookClient6 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient6_thumb.jpg" width=681 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart2BuildingtheOutlookAddIn_8AC8/OutlookClient6_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;One tip to remove the Outlook Add-in when you're done debugging is to select Build --&amp;gt; Clean Solution menu item in Visual Studio to unregister the Add-In. &lt;/P&gt;
&lt;P&gt;I've &lt;A href="http://code.msdn.microsoft.com/OBANorthwind/" target=_blank mce_href="http://code.msdn.microsoft.com/OBANorthwind/"&gt;uploaded the code that we've talked about so far in this series to Code Gallery&lt;/A&gt; so have a look. I'll continue adding releases to this as we build the other pieces of the OBA. Next post I'll show how we can create a purchase order in Word 2007 and use that to automatically feed Order data into the Northwind database.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9405756" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Visual+Basic/default.aspx">Visual Basic</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Office/default.aspx">Office</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/OBA/default.aspx">OBA</category></item><item><title>OBA Part 1 - Exposing Line-of-Business Data</title><link>http://blogs.msdn.com/bethmassi/archive/2009/02/03/oba-part-1-exposing-line-of-business-data.aspx</link><pubDate>Wed, 04 Feb 2009 01:23:24 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9393912</guid><dc:creator>Beth Massi</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9393912.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9393912</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9393912</wfw:comment><description>&lt;p&gt;Last post I talked about the &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/02/02/building-an-office-business-application-for-techready-8.aspx" target="_blank"&gt;high-level architecture of our &lt;strong&gt;O&lt;/strong&gt;ffice &lt;strong&gt;B&lt;/strong&gt;usiness &lt;strong&gt;A&lt;/strong&gt;pplication&lt;/a&gt; for the new Northwind Traders. There are a lot of different architecture options to consider when building an OBA. OBA is all about using Microsoft Office with your Line of Business (LOB) data. Whether that involves using SharePoint as well depends on the application. Since we wanted to store the unstructured data (the Northwind customer P.O.)&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart1ExposingLineofBusinessData_8D7A/OBAdiagram_2.jpg"&gt;&lt;img style="margin: 5px 10px 0px 0px" height="159" alt="OBAdiagram" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart1ExposingLineofBusinessData_8D7A/OBAdiagram_thumb.jpg" width="156" align="left" border="0" /&gt;&lt;/a&gt; SharePoint is a good fit here.&lt;/p&gt;  &lt;p&gt;There are a lot of options when thinking about how to expose your LOB data. For instance, you may already have a service oriented architecture at the enterprise that exposes data contracts and processes that you can consume from Office clients. Or maybe you have a small business and have decided to expose &lt;font color="#ff0000"&gt;&lt;font color="#000000"&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/cc138242.aspx" target="_blank"&gt;a simple service that returns and consumes n-tier DataSets&lt;/a&gt;&lt;/font&gt; &lt;/font&gt;directly. Or you already have a custom LOB data entry system using custom business objects and you want to reuse the business layer in the Office client. OBA doesn't dictate &lt;em&gt;how &lt;/em&gt;you expose this data. Because you can consume data in Office clients the same way you do in Windows apps the same types of decisions need to be made. &lt;/p&gt;  &lt;p&gt;When we sat down to write the new Northwind Traders application we thought about how our data would need to behave and what would be the best way for all the pieces to easily update and query the Northwind database. Because there was only going to be simple validations needed on the data and mostly CRUD operations we opted to expose an Entity Data Model via ADO.NET Data Services &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target="_blank"&gt;like I showed before&lt;/a&gt;. This allowed us to get a secure service up and running in minutes. &lt;/p&gt;  &lt;p&gt;We did make some minor changes to our old friend, the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;amp;displaylang=en" target="_blank"&gt;Northwind database&lt;/a&gt;. First, since we wanted to be able to look up order history for a customer when they emailed the sales reps, we needed to add an EmailAddress field to the Customers table (amazing that we didn't have that field before!). We also added it to the Employees table. &lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;ALTER TABLE &lt;/span&gt;dbo.Customers &lt;span style="color: blue"&gt;ADD
    &lt;/span&gt;EmailAddress &lt;span style="color: blue"&gt;varchar&lt;/span&gt;(50) &lt;span style="color: blue"&gt;NULL
&lt;/span&gt;GO
&lt;span style="color: blue"&gt;ALTER TABLE &lt;/span&gt;dbo.Employees &lt;span style="color: blue"&gt;ADD
    &lt;/span&gt;EmailAddress &lt;span style="color: blue"&gt;varchar&lt;/span&gt;(50) &lt;span style="color: blue"&gt;NULL
&lt;/span&gt;GO&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Then we populated the data with some customers and employees that were actually folks on our team because we need real email addresses to work with :-)&lt;/p&gt;

&lt;p&gt;Next I created a new ASP.NET Web Application and added an ADO.NET Data Service and an Entity Data Model just like how &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target="_blank"&gt;I showed in this post&lt;/a&gt;. (You will need &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=27673c47-b3b5-4c67-bd99-84e525b5ce61&amp;amp;displaylang=en" target="_blank"&gt;Visual Studio 2008 Service Pack 1&lt;/a&gt; in order to get these new item templates.) For testing we set the service to allow full access to all the entities in the model&amp;#160; -- we'll lock it down later. I also am passing detailed errors which we won't want to do once we're in production:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Northwind
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;DataService(&lt;span style="color: blue"&gt;Of &lt;/span&gt;NorthwindEntities)

    &lt;span style="color: green"&gt;' This method is called only once to initialize service-wide policies.
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Shared Sub &lt;/span&gt;InitializeService(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;config &lt;span style="color: blue"&gt;As &lt;/span&gt;IDataServiceConfiguration)
        config.SetEntitySetAccessRule(&lt;span style="color: #a31515"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;, EntitySetRights.All)
        config.UseVerboseErrors = &lt;span style="color: blue"&gt;True
    End Sub&lt;br /&gt;End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;One thing we did want to do is set up our data model so that it enforced constraints (i.e. there cannot be an Order without a Customer) but since some of our legacy data didn't specify all of these constraints we made the changes to the model instead, so that the integrity on all new data would be enforced through the service. This is often the case in projects, you cannot change the legacy databases but you still need to work with proper data models. So we changed the EDM so that all the entities were singular and not plural (Customer instead of Customers, Order instead of Orders, etc). We also changed the associations so that they were enforced and so that one to many collections were plural and the one-to-one were singular (i.e. Order has Order_Details collection and Order_Detail has Product reference). You can modify these from the Properties window of the &lt;font color="#ff0000"&gt;&lt;font color="#000000"&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb738482.aspx" target="_blank"&gt;Entity Data Model Designer.&lt;/a&gt;&lt;/font&gt; &lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart1ExposingLineofBusinessData_8D7A/OBAedm_4.jpg"&gt;&lt;img height="475" alt="OBAedm" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/OBAPart1ExposingLineofBusinessData_8D7A/OBAedm_thumb_1.jpg" width="641" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Once I have the model and the data service code set up we can hit F5 and navigate our browser to the Northwind.svc and test the call to pull up all the customers (i.e. http://localhost:1234/Northwind.svc/Customers) just like how &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target="_blank"&gt;I showed in this post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that we have our data exposed as a data service we can build the Office clients to interact with it just like I showed before &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/22/ado-net-data-services-building-an-excel-client.aspx" target="_blank"&gt;here when we built a simple Excel client&lt;/a&gt;. Next post I'll show how we can use WPF controls in an Outlook Add-In in order to display the customer order history by querying the data through the data service. &lt;/p&gt;

&lt;p&gt;Until next time...&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9393912" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Data/default.aspx">Data</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Entity+Framework/default.aspx">Entity Framework</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/OBA/default.aspx">OBA</category></item><item><title>Building an Office Business Application for TechReady 8</title><link>http://blogs.msdn.com/bethmassi/archive/2009/02/02/building-an-office-business-application-for-techready-8.aspx</link><pubDate>Tue, 03 Feb 2009 03:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9392479</guid><dc:creator>Beth Massi</dc:creator><slash:comments>18</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9392479.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9392479</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9392479</wfw:comment><description>&lt;P&gt;The last week I've been working with a couple teammates on an Office Business Application (OBA) demonstration we wanted to put together for TechReady 8. TechReady is an internal conference we deliver to the field employees. It's my first one and so far it's been pretty fun. This morning Scott Hanselman hosted an "UnKeynote" that showcased a lot of the new stuff coming in Visual Studio 2010 that I can't talk about yet but believe me it was cool. ;-)&lt;/P&gt;
&lt;P&gt;The application I helped build with Rachel and Mike on my team was a total blast. We wanted to demonstrate using Office as a client to Line-of-Business data as well as show some of the nifty features of SharePoint workflows. So we decided it was time to bring poor Northwind Traders into the 21st century. Here's what we came up with:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/BuildinganOfficeBusinessApplicationforTe_CD9B/OBANorthwind_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/BuildinganOfficeBusinessApplicationforTe_CD9B/OBANorthwind_2.jpg"&gt;&lt;IMG border=0 alt=OBANorthwind src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/BuildinganOfficeBusinessApplicationforTe_CD9B/OBANorthwind_thumb.jpg" width=683 height=484 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/BuildinganOfficeBusinessApplicationforTe_CD9B/OBANorthwind_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;We needed a way to easily and securely expose our LOB data -- the Northwind database -- to the enterprise. So we created an entity data model against our SQL Server Northwind database and then exposed it using &lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx"&gt;ADO.NET Data Services&lt;/A&gt; . The Northwind sales reps do all of their work in Outlook, communicating with our high-volume customers. So we built an Outlook Add-in that they can use to look up the customer order history from the database and easily work with purchase orders. The Add-in displays a form region with the customer order history in an adjoining area below when they open the email. &lt;/P&gt;
&lt;P&gt;The orders are then submitted to a SharePoint document library as Word 2007 documents with XML data specified via content controls. A SharePoint Workflow then shreds this document data (using VB XML literals support and the Open XML SDK) and passes it to the ADO.NET data Service which persists the data in the database. This was written as a SharePoint sequential workflow.&lt;/P&gt;
&lt;P&gt;We also built an Excel client for our shipping department to use that displays the orders that are ready to ship which allows them to update the ship date and save it back to through the data service. It also shows the products and quantities ordered in an Action Pane and does some data analysis using a pivot table and pie chart to show the breakdown of shipping cities and freight cost. We also used WPF user controls in the Outlook and Excel clients so that we could match the look-and-feel of Office. &lt;/P&gt;
&lt;P&gt;Finally we created a web part for the SharePoint site that displays key performance indicators like oversold products and our top customer sales.&lt;/P&gt;
&lt;P&gt;I have to say it was a very fun project to work on and I personally learned a lot about Excel and WPF as well as the OBA architecture. We spend about 3 days building this and I was pleasantly surprised how well the tools worked together. The pieces we built were predominantly in Visual Studio 2008 by Rachel and I and Mike handled the bleeding edge SharePoint parts.&lt;/P&gt;
&lt;P&gt;In the next few blog posts I'll go into the details of building WPF user controls in the Excel and Outlook clients and how we exposed a simple, clean data model against the not-so-clean Northwind database. I'll also show the technique of how we easily stripped the order data out of the Word 2007 documents. &lt;/P&gt;
&lt;P&gt;For now, some good links on OBA and VSTO development:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/vsto/dd164303.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/vsto/dd164303.aspx"&gt;Office Development Videos&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.com/vsto" target=_blank mce_href="http://msdn.com/vsto"&gt;Office Development with Visual Studio&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/22/ado-net-data-services-building-an-excel-client.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/22/ado-net-data-services-building-an-excel-client.aspx"&gt;ADO.NET Data Services - Building an Excel Client&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/vsto/" target=_blank mce_href="http://blogs.msdn.com/vsto/"&gt;Office Development with Visual Studio Team Blog&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Until next time....&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;UPDATE&lt;/STRONG&gt;&amp;nbsp;- Here is the full set of articles and code: &lt;A href="http://code.msdn.microsoft.com/OBANorthwind"&gt;http://code.msdn.microsoft.com/OBANorthwind&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9392479" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Visual+Basic/default.aspx">Visual Basic</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Office/default.aspx">Office</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Data/default.aspx">Data</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2010/default.aspx">VS2010</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VSTO/default.aspx">VSTO</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/OBA/default.aspx">OBA</category></item><item><title>ADO.NET Data Services - Building an Excel Client</title><link>http://blogs.msdn.com/bethmassi/archive/2009/01/22/ado-net-data-services-building-an-excel-client.aspx</link><pubDate>Fri, 23 Jan 2009 09:46:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9372251</guid><dc:creator>Beth Massi</dc:creator><slash:comments>13</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9372251.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9372251</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9372251</wfw:comment><description>&lt;p&gt;Last few posts I've been building a WPF client against ADO.NET Data Services, if you missed them:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx"&gt;Using ADO.NET Data Services&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/15/ado-net-data-services-building-a-wpf-client.aspx"&gt;ADO.NET Data Services - Building a WPF Client&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/20/ado-net-data-services-enforcing-fk-associations-and-a-fix-for-deleting-entities.aspx"&gt;ADO.NET Data Services - Enforcing FK Associations and a Fix for Deleting Entities&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/21/ado-net-data-services-intercepting-queries-and-adding-validation.aspx"&gt;ADO.NET Data Services - Intercepting Queries and Adding Validation&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Today I want to show a simple Excel client that queries our service and allows us to edit the customers in Northwind. I'm going to use Visual Studio 2008 (VSTO) to build a &lt;a href="http://msdn.microsoft.com/en-us/library/zcfbd2sk.aspx" target="_blank"&gt;document-level customization&lt;/a&gt; against an Excel 2007 Workbook. We'll also build an &lt;a href="http://msdn.microsoft.com/en-us/library/7we49he1.aspx" target="_blank"&gt;Actions Pane&lt;/a&gt; that allows us to query and save customers to our ADO.NET data service. Excel's tabular data format lends itself well to CRUD database operations when we Add, Delete and Update rows in a Sheet. (NOTE: You cannot create Office solutions in Visual Studio Express editions.)&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Setting Permissions on Customers&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The first thing we need to do on our data service is allow access to the Customers entity set on our data model. &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target="_blank"&gt;In the first article&lt;/a&gt; I showed how to set up our service and permissions. For this example we'll be building upon the same data service we used for the WPF client which works with Product and Categories so I'll just need to add access to Customers:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Northwind
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;DataService(&lt;span style="color: blue"&gt;Of &lt;/span&gt;NorthwindEntities)

    &lt;span style="color: green"&gt;' This method is called only once to initialize service-wide policies.
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Shared Sub &lt;/span&gt;InitializeService(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;config &lt;span style="color: blue"&gt;As &lt;/span&gt;IDataServiceConfiguration)
        config.SetEntitySetAccessRule(&lt;span style="color: #a31515"&gt;&amp;quot;Products&amp;quot;&lt;/span&gt;, EntitySetRights.All)
        config.SetEntitySetAccessRule(&lt;span style="color: #a31515"&gt;&amp;quot;Categories&amp;quot;&lt;/span&gt;, EntitySetRights.AllRead)
&lt;strong&gt;        config.SetEntitySetAccessRule(&lt;span style="color: #a31515"&gt;&amp;quot;Customers&amp;quot;&lt;/span&gt;, EntitySetRights.All)
&lt;/strong&gt;    &lt;span style="color: blue"&gt;End Sub&lt;br /&gt;...&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;Creating an Excel Client&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next we'll add the Excel 2007 project to the same solution we've been working on to make things simple for debugging. However, it's important to note that when we want to deploy the Excel (or WPF) client we should place the project into it's own solution. (For more information on deploying Office solutions, &lt;a href="http://msdn.microsoft.com/en-us/library/bb821233.aspx" target="_blank"&gt;read this article&lt;/a&gt;.) You would also need to &lt;a href="http://msdn.microsoft.com/en-us/library/aa751792.aspx" target="_blank"&gt;deploy the ADO.NET Data Service just like any other WCF Service&lt;/a&gt; to an IIS server first before deploying any clients.&lt;/p&gt;

&lt;p&gt;Right-click on the solution and Add --&amp;gt; New Project then select the Office --&amp;gt; 2007 category on the left and choose the Excel 2007 Workbook project.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildinganExcelClient_DFF4/AstoriaExcel_4.jpg"&gt;&lt;img height="407" alt="AstoriaExcel" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildinganExcelClient_DFF4/AstoriaExcel_thumb_1.jpg" width="640" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Next &lt;a href="http://msdn.microsoft.com/en-us/library/bb628652.aspx" target="_blank"&gt;add the service reference&lt;/a&gt; to the data service by right-clicking on the Excel project and selecting Add Service Reference. This is exactly how we added the service reference to our WPF client which generates the client proxy and entity types for us.&lt;/p&gt;

&lt;table cellspacing="0" cellpadding="2" width="100%" border="0"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td valign="top" width="5%"&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildinganExcelClient_DFF4/AstoriaExcel1_2.jpg"&gt;&lt;img style="margin: 0px 15px 0px 0px" height="315" alt="AstoriaExcel1" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildinganExcelClient_DFF4/AstoriaExcel1_thumb.jpg" width="244" border="0" /&gt;&lt;/a&gt;&lt;/td&gt;

      &lt;td valign="top" width="95%"&gt;Now add a New Item and select &lt;a href="http://msdn.microsoft.com/en-us/library/e3zbk0hz.aspx" target="_blank"&gt;Actions Pane Control&lt;/a&gt;. This will open up the designer and we can add Windows Forms or &lt;a href="http://msdn.microsoft.com/en-us/library/bb772076.aspx" target="_blank"&gt;WPF controls onto the pane&lt;/a&gt;. If we want to add WPF controls then first create a WPF user control and then add an &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx" target="_blank"&gt;ElementHost&lt;/a&gt; onto the pane and then you can specify which WPF user control to display. In this example all I'm going to need is a label, a couple textboxes and a couple buttons so I'm going to just use Windows Forms controls, nothing fancy here. The pane will allow the user to specify a filter on country and find customers that match as well as save changes back. I also added a multi-line, readonly textbox for status messages below the buttons.

        &lt;br /&gt;

        &lt;br /&gt;We'll come back to the code for this actions pane after we set up our data source. The data source will be the list of customer entities returned from the service. &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Tracking Changes on Customer Entities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our actions pane is going to control how we query and save the customers. But instead of interacting with the service client proxy directly I'm going to create a class that inherits from a BindingList(Of Customer) so that we can also encapsulate the tracking of adds, updates and deletes of the customers that we bring down from the service. This class will also have a method to execute a customer query filtered by a specified country as well as a method to save changes. Finally we'll need to override some BindingList methods that will allow us to tell the data service client whether to add, update or delete as the customer entities are added to, updated or removed from the list.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;ExcelClient.NorthwindService
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.ComponentModel

&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;MyCustomerList
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;BindingList(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Customer)

    &lt;span style="color: blue"&gt;Private &lt;/span&gt;DataServiceContext &lt;span style="color: blue"&gt;As New &lt;/span&gt;NorthwindEntities(&lt;span style="color: blue"&gt;New &lt;/span&gt;Uri(&lt;span style="color: #a31515"&gt;&amp;quot;http://localhost:1234/Northwind.svc&amp;quot;&lt;/span&gt;))
    &lt;span style="color: blue"&gt;Private &lt;/span&gt;_isAdding &lt;span style="color: blue"&gt;As Boolean
    Private &lt;/span&gt;_isSaving &lt;span style="color: blue"&gt;As Boolean
    Private &lt;/span&gt;_hasChanges &lt;span style="color: blue"&gt;As Boolean

    Public ReadOnly Property &lt;/span&gt;HasChanges() &lt;span style="color: blue"&gt;As Boolean
        Get
            Return &lt;/span&gt;_hasChanges
        &lt;span style="color: blue"&gt;End Get
    End Property

    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Queries the customers from the ADO.NET Data Service 
    ''' and returns the number of customers returned in the results
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param name=&amp;quot;country&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;The country to use in the query filter&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/param&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;number of customers returned from the service&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/returns&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Function &lt;/span&gt;FillCustomersByCountry(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;country &lt;span style="color: blue"&gt;As String&lt;/span&gt;) &lt;span style="color: blue"&gt;As Integer
        Dim &lt;/span&gt;i = 0
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;customers = &lt;span style="color: blue"&gt;From &lt;/span&gt;c &lt;span style="color: blue"&gt;In &lt;/span&gt;DataServiceContext.Customers _
                        &lt;span style="color: blue"&gt;Where &lt;/span&gt;c.Country = country _
                        &lt;span style="color: blue"&gt;Order By &lt;/span&gt;c.CustomerID

        &lt;span style="color: blue"&gt;For Each &lt;/span&gt;c &lt;span style="color: blue"&gt;In &lt;/span&gt;customers
            &lt;span style="color: blue"&gt;Me&lt;/span&gt;.Add(c)
            i += 1
        &lt;span style="color: blue"&gt;Next
        Return &lt;/span&gt;i
    &lt;span style="color: blue"&gt;End Function

    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' Saves the customer changes back to the service.
    ''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;true if save was successful, otherwise an exception is thrown&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/returns&amp;gt;
    &lt;/span&gt;&lt;span style="color: green"&gt;''' &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Function &lt;/span&gt;SaveChanges() &lt;span style="color: blue"&gt;As Boolean
        Dim &lt;/span&gt;saved &lt;span style="color: blue"&gt;As Boolean
        Try
            &lt;/span&gt;_isSaving = &lt;span style="color: blue"&gt;True
            Me&lt;/span&gt;.DataServiceContext.SaveChanges()
            _hasChanges = &lt;span style="color: blue"&gt;False
            &lt;/span&gt;saved = &lt;span style="color: blue"&gt;True
        Finally
            &lt;/span&gt;_isSaving = &lt;span style="color: blue"&gt;False
        End Try

        Return &lt;/span&gt;saved
    &lt;span style="color: blue"&gt;End Function

    Protected Overrides Function &lt;/span&gt;AddNewCore() &lt;span style="color: blue"&gt;As Object
        &lt;/span&gt;_isAdding = &lt;span style="color: blue"&gt;True
        Return MyBase&lt;/span&gt;.AddNewCore()
    &lt;span style="color: blue"&gt;End Function

    Protected Overrides Sub &lt;/span&gt;RemoveItem(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;index &lt;span style="color: blue"&gt;As Integer&lt;/span&gt;)
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;c = &lt;span style="color: blue"&gt;Me&lt;/span&gt;(index)
        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.DataServiceContext.DeleteObject(c)
        _hasChanges = &lt;span style="color: blue"&gt;True
        MyBase&lt;/span&gt;.RemoveItem(index)
    &lt;span style="color: blue"&gt;End Sub

    Protected Overrides Sub &lt;/span&gt;OnListChanged(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;System.ComponentModel.ListChangedEventArgs)
        &lt;span style="color: blue"&gt;If Not &lt;/span&gt;_isSaving &lt;span style="color: blue"&gt;Then
            &lt;/span&gt;&lt;span style="color: green"&gt;'The Customer partial class will need to implement 
            ' INotifyPropertyChanged for this will work
            &lt;/span&gt;&lt;span style="color: blue"&gt;If &lt;/span&gt;e.ListChangedType = ListChangedType.ItemChanged &lt;span style="color: blue"&gt;Then
                If &lt;/span&gt;_isAdding &lt;span style="color: blue"&gt;Then
                    Me&lt;/span&gt;.DataServiceContext.AddToCustomers(&lt;span style="color: blue"&gt;Me&lt;/span&gt;(e.NewIndex))
                    _isAdding = &lt;span style="color: blue"&gt;False
                Else
                    Me&lt;/span&gt;.DataServiceContext.UpdateObject(&lt;span style="color: blue"&gt;Me&lt;/span&gt;(e.NewIndex))
                &lt;span style="color: blue"&gt;End If
                &lt;/span&gt;_hasChanges = &lt;span style="color: blue"&gt;True
            End If
            MyBase&lt;/span&gt;.OnListChanged(e)
        &lt;span style="color: blue"&gt;End If
    End Sub

End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;In order for the OnListChanged event to fire when a property on a customer entity is changed we will need to extend the partial class generated on the client. We'll need to Implement &lt;a href="http://msdn.microsoft.com/en-us/library/ms229614.aspx" target="_blank"&gt;INotifyPropertyChanged&lt;/a&gt; and overwrite some partial methods just like we did to our product entity in &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/21/ado-net-data-services-intercepting-queries-and-adding-validation.aspx" target="_blank"&gt;the last post&lt;/a&gt; when we added validation. It's important to make sure the partial class is in the same namespace as the client service reference. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;ExcelClient.NorthwindService
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.ComponentModel

&lt;span style="color: blue"&gt;Namespace &lt;/span&gt;NorthwindService

    &lt;span style="color: blue"&gt;Partial Public Class &lt;/span&gt;Customer
        &lt;span style="color: blue"&gt;Implements &lt;/span&gt;INotifyPropertyChanged

        &lt;span style="color: blue"&gt;Public Event &lt;/span&gt;PropertyChanged(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;sender &lt;span style="color: blue"&gt;As Object&lt;/span&gt;, &lt;span style="color: blue"&gt;ByVal &lt;/span&gt;e &lt;span style="color: blue"&gt;As &lt;/span&gt;PropertyChangedEventArgs) _
                     &lt;span style="color: blue"&gt;Implements &lt;/span&gt;INotifyPropertyChanged.PropertyChanged

        &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;FirePropertyChanged(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;propertyName &lt;span style="color: blue"&gt;As String&lt;/span&gt;)
            &lt;span style="color: blue"&gt;If &lt;/span&gt;propertyName &amp;lt;&amp;gt; &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;Then
                RaiseEvent &lt;/span&gt;PropertyChanged(&lt;span style="color: blue"&gt;Me&lt;/span&gt;, &lt;span style="color: blue"&gt;New &lt;/span&gt;PropertyChangedEventArgs(propertyName))
            &lt;span style="color: blue"&gt;End If
        End Sub

        Private Sub &lt;/span&gt;OnAddressChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;Address&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnCityChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;City&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnCompanyNameChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;CompanyName&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnContactNameChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;ContactName&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnContactTitleChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;ContactTitle&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnCountryChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;Country&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnCustomerIDChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;CustomerID&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnFaxChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;Fax&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnPhoneChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;Phone&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnPostalCodeChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;PostalCode&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub

        Private Sub &lt;/span&gt;OnRegionChanged()
            FirePropertyChanged(&lt;span style="color: #a31515"&gt;&amp;quot;Region&amp;quot;&lt;/span&gt;)
        &lt;span style="color: blue"&gt;End Sub
       
    End Class
End Namespace
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Binding an Excel Sheet to the Customer List&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;Now that we have a way to track our customer entities we can work with them on an Excel Sheet by binding them to a &lt;a href="http://msdn.microsoft.com/en-us/library/2ttzcbhb.aspx" target="_blank"&gt;ListObject control&lt;/a&gt;. First open up the data sources window (on the main menu select Data --&amp;gt; Show Data Sources) and then add a new data source and select the Object data source type. Then expand the ExcelClient.NorthwindService namespace and select the Customer object. Now open up Sheet1 in the project to open the Excel designer and drag the Customer onto the Sheet, this will create a ListObject control that is bound to a CustomerBindingSource. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildinganExcelClient_DFF4/AstoriaExcel2_2.jpg"&gt;&lt;img height="309" alt="AstoriaExcel2" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildinganExcelClient_DFF4/AstoriaExcel2_thumb.jpg" width="640" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Right-click on the sheet and View Code. All we need to do is set the CustomerBindingSource.DataSource property to an instance of our MyCustomerList. I'm going to make the list a public field of the Sheet so the Actions Pane can interact with it easily.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Sheet1

    &lt;span style="color: blue"&gt;Public &lt;/span&gt;CustomerList &lt;span style="color: blue"&gt;As New &lt;/span&gt;MyCustomerList()

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;Sheet1_Startup() &lt;span style="color: blue"&gt;Handles Me&lt;/span&gt;.Startup
        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.CustomerBindingSource.DataSource = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.CustomerList
    &lt;span style="color: blue"&gt;End Sub

End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Hooking Up the Actions Pane&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;In order to add an Actions Pane to an Excel Workbook we need to open up the Workbook code-behind so double-click on ThisWorkbook in the project and add the pane to the ActionPane.Controls collection like so:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;ThisWorkbook

    &lt;span style="color: blue"&gt;Public &lt;/span&gt;CustomerActions &lt;span style="color: blue"&gt;As New &lt;/span&gt;CustomerActionsPane()

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;ThisWorkbook_Startup() &lt;span style="color: blue"&gt;Handles Me&lt;/span&gt;.Startup
        &lt;span style="color: blue"&gt;Me&lt;/span&gt;.ActionsPane.Controls.Add(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.CustomerActions)
    &lt;span style="color: blue"&gt;End Sub

End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now back in the CustomerActionsPane we can write code to interact with the CustomerList on Sheet1. We'll just add some code to the click event handlers of our buttons. First the Find button click handler will attempt to grab a reference to the CustomerList on Sheet1 and then it will call the FillCustomersByCountry method we created:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;CustomerActionsPane

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;cmdFind_Click() &lt;span style="color: blue"&gt;Handles &lt;/span&gt;cmdFind.Click
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;msg = &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;
        &lt;/span&gt;&lt;span style="color: blue"&gt;Try
            Dim &lt;/span&gt;searchTerm = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.txtSearchTerm.Text.Trim()
            &lt;span style="color: blue"&gt;If &lt;/span&gt;searchTerm &amp;lt;&amp;gt; &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;Then

                Dim &lt;/span&gt;list = ExcelClient.Globals.Sheet1.CustomerList
                &lt;span style="color: blue"&gt;Dim &lt;/span&gt;count = list.FillCustomersByCountry(searchTerm)

                msg = &lt;span style="color: blue"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;{0} customers returned from server.&amp;quot;&lt;/span&gt;, count)
            &lt;span style="color: blue"&gt;Else
                &lt;/span&gt;msg = &lt;span style="color: #a31515"&gt;&amp;quot;Please enter a country filter.&amp;quot;
            &lt;/span&gt;&lt;span style="color: blue"&gt;End If

        Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            msg = ex.ToString
        &lt;span style="color: blue"&gt;End Try
        Me&lt;/span&gt;.txtStatus.Text = msg
    &lt;span style="color: blue"&gt;End Sub&lt;br /&gt;...&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;Handling Exceptions from the Data Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next we need to write the code for our Save button click handler. Here we need to anticipate exceptions coming back from our database. By default we don't expose verbose exception details from our data service because this could give malicious hackers clues into the architecture of our service or worse our database structure. So what we get back from the ADO.NET data service is a DataServiceRequestException with a generic message. You can add additional information to this exception by overriding the &lt;a href="http://msdn.microsoft.com/en-us/library/cc646827.aspx" target="_blank"&gt;HandleException method&lt;/a&gt; on the data service itself. For instance we could do something like this to return database exceptions: &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Northwind
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;DataService(&lt;span style="color: blue"&gt;Of &lt;/span&gt;NorthwindEntities)

    &lt;span style="color: green"&gt;' This method is called only once to initialize service-wide policies.
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Shared Sub &lt;/span&gt;InitializeService(...&lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;    Protected Overrides Sub &lt;/span&gt;HandleException(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;args &lt;span style="color: blue"&gt;As &lt;/span&gt;HandleExceptionArgs)

        &lt;span style="color: blue"&gt;If &lt;/span&gt;args.Exception.InnerException &lt;span style="color: blue"&gt;IsNot Nothing Then
            If TypeOf &lt;/span&gt;args.Exception.InnerException &lt;span style="color: blue"&gt;Is &lt;/span&gt;SqlClient.SqlException &lt;span style="color: blue"&gt;Then
                &lt;/span&gt;&lt;span style="color: green"&gt;'If we have config.UseVerboseErrors = True in the InitializeService
                ' then the InnerException (last parameter) will be serialized in detail
                ' including SQL message and full stack trace otherwise just the generic 
                ' message below will be returned. 
                &lt;/span&gt;args.Exception = &lt;span style="color: blue"&gt;New &lt;/span&gt;DataServiceException(args.ResponseStatusCode, _
                        TypeName(args.Exception.InnerException), _
                        &lt;span style="color: #a31515"&gt;&amp;quot;The database could not save the data. Check constraints.&amp;quot;&lt;/span&gt;, _
                        &lt;span style="color: #a31515"&gt;&amp;quot;en-US&amp;quot;&lt;/span&gt;, _
                         args.Exception.InnerException)

            &lt;span style="color: blue"&gt;End If
        End If
        &lt;/span&gt;&lt;span style="color: green"&gt;'TODO: Log the exception
&lt;/span&gt;&lt;span style="color: blue"&gt;    End Sub&lt;/span&gt;&lt;span style="color: blue"&gt;&lt;br /&gt;...&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The message that is returned, however, is an XML document which contains different information depending on if we have config.UseVerboseErrors set to True in the InitializeService method or not. If we're not (the default) then the XML document returned from this handler would look like:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #844646"&gt;xml &lt;/span&gt;&lt;span style="color: #b96464"&gt;version&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;1.0&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot; &lt;/span&gt;&lt;span style="color: #b96464"&gt;encoding&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;utf-8&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot; &lt;/span&gt;&lt;span style="color: #b96464"&gt;standalone&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;yes&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;?&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;error &lt;/span&gt;&lt;span style="color: #b96464"&gt;xmlns&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;code&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #555555"&gt;SqlException&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;code&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;message &lt;/span&gt;&lt;span style="color: #b96464"&gt;xml:lang&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;en-US&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
         &lt;/span&gt;&lt;span style="color: #555555"&gt;The database could not save the data. Check constraints.
    &lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;message&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;error&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;If we did have config.UseVerboseErrors = True in the InitializeService then the XML document would be:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #844646"&gt;xml &lt;/span&gt;&lt;span style="color: #b96464"&gt;version&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;1.0&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot; &lt;/span&gt;&lt;span style="color: #b96464"&gt;encoding&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;utf-8&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot; &lt;/span&gt;&lt;span style="color: #b96464"&gt;standalone&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;yes&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;?&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;error &lt;/span&gt;&lt;span style="color: #b96464"&gt;xmlns&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;code&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #555555"&gt;SqlException&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;code&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;message &lt;/span&gt;&lt;span style="color: #b96464"&gt;xml:lang&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;en-US&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
        &lt;/span&gt;&lt;span style="color: #555555"&gt;The database could not save the data. Check constraints.
    &lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;message&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;innererror &lt;/span&gt;&lt;span style="color: #b96464"&gt;xmlns&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;xmlns&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;message&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
            &lt;/span&gt;&lt;span style="color: #555555"&gt;The DELETE statement conflicted with the REFERENCE constraint &amp;quot;FK_Orders_Customers&amp;quot;...
        &lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;message&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;type&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #555555"&gt;System.Data.SqlClient.SqlException&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;type&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;stacktrace&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
            &lt;/span&gt;&lt;span style="color: #555555"&gt;at System.Data.SqlClient.SqlConnection.OnError(SqlException...full stack trace...
        &lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;stacktrace&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;innererror&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;error&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;It's definitely not a good idea to return database details in error messages so make sure your production code does not have UseVerboseErrors set to True. &lt;/p&gt;

&lt;p&gt;So back on our actions pane we can hook up the Save button click handler and write a few lines of code to extract any message from the XML. First we need to add an XML namespace Import because the error document declares a default namespace as seen above. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Data.Services.Client
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #b96464"&gt;xmlns&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;

&lt;/span&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;CustomerActionsPane

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;cmdFind_Click(...
&lt;span style="color: blue"&gt;
    Private Sub &lt;/span&gt;cmdSave_Click() &lt;span style="color: blue"&gt;Handles &lt;/span&gt;cmdSave.Click
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;msg = &lt;span style="color: #a31515"&gt;&amp;quot;Customers could not be saved.&amp;quot; &lt;/span&gt;&amp;amp; vbCrLf
        &lt;span style="color: blue"&gt;Try
            Dim &lt;/span&gt;list = ExcelClient.Globals.Sheet1.CustomerList

            &lt;span style="color: blue"&gt;If &lt;/span&gt;list.SaveChanges() &lt;span style="color: blue"&gt;Then
                &lt;/span&gt;msg = &lt;span style="color: #a31515"&gt;&amp;quot;Customers saved.&amp;quot;
            &lt;/span&gt;&lt;span style="color: blue"&gt;End If

        Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;DataServiceRequestException &lt;span style="color: blue"&gt;When &lt;/span&gt;ex.InnerException &lt;span style="color: blue"&gt;IsNot Nothing
            Try
                Dim &lt;/span&gt;xmlError = XElement.Parse(ex.InnerException.Message)
                msg &amp;amp;= xmlError.&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;message&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.Value

            &lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex1 &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception &lt;span style="color: green"&gt;'message isn't xml, so display string
                &lt;/span&gt;msg &amp;amp;= ex.InnerException.ToString()
            &lt;span style="color: blue"&gt;End Try

        Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
            msg &amp;amp;= ex.ToString
        &lt;span style="color: blue"&gt;End Try

        Me&lt;/span&gt;.txtStatus.Text = msg
    &lt;span style="color: blue"&gt;End Sub
End Class&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;strong&gt;Running the Excel Client&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that we've got all our code written let's open up &lt;a href="http://www.fiddler2.com/fiddler2/version.asp" target="_blank"&gt;Fiddler&lt;/a&gt; and SQL Profiler and run this baby. After the Actions Pane opens we can click the Find button and the Customer list is populated and we can see it on our Sheet. From here we can add a new row or modify rows and the changes will be tracked in our list. We can also delete rows as well by right-clicking on the row and selecting Delete. (click image to enlarge)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildinganExcelClient_DFF4/AstoriaExcel3_2.jpg"&gt;&lt;img height="499" alt="AstoriaExcel3" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildinganExcelClient_DFF4/AstoriaExcel3_thumb.jpg" width="690" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Slick! Note that we will trigger a constraint violation if we attempt to delete a Customer that has Orders and this will cause our ExceptionHandler to return a generic message that is displayed in the status message area. We're not doing it in this example but you can opt to continue processing the rest of the changes by indicating that option in the SaveChanges method. In that case you'll get a DataServiceRespons object back that you can inspect for errors on the offending submissions. I'll expand on that in a follow-up post.&lt;/p&gt;

&lt;p&gt;I've added a &lt;a href="http://code.msdn.microsoft.com/astoriaexcel/" target="_blank"&gt;new Code Gallery sample&lt;/a&gt; so you can download it and play with the Excel client. It also includes the &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/15/ado-net-data-services-building-a-wpf-client.aspx" target="_blank"&gt;WPF client&lt;/a&gt; we built in the previous posts. &lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9372251" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Visual+Basic/default.aspx">Visual Basic</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Office/default.aspx">Office</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/N-tier/default.aspx">N-tier</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VSTO/default.aspx">VSTO</category></item><item><title>ADO.NET Data Services - Intercepting Queries and Adding Validation</title><link>http://blogs.msdn.com/bethmassi/archive/2009/01/21/ado-net-data-services-intercepting-queries-and-adding-validation.aspx</link><pubDate>Thu, 22 Jan 2009 07:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9362890</guid><dc:creator>Beth Massi</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9362890.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9362890</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9362890</wfw:comment><description>&lt;P&gt;Last few posts I've been building a WPF client against ADO.NET Data Services, if you missed them:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx"&gt;Using ADO.NET Data Services&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/15/ado-net-data-services-building-a-wpf-client.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/15/ado-net-data-services-building-a-wpf-client.aspx"&gt;ADO.NET Data Services - Building a WPF Client&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/20/ado-net-data-services-enforcing-fk-associations-and-a-fix-for-deleting-entities.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/20/ado-net-data-services-enforcing-fk-associations-and-a-fix-for-deleting-entities.aspx"&gt;ADO.NET Data Services - Enforcing FK Associations and a Fix for Deleting Entities&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Today I want to show you how we can add validation or any other extra processing when data is queried from the data service as well as when we attempt to make changes to the data. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Ways of Querying a ADO.NET Data Service&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;First let's recap how we can query a data service. In our WPF client we've been taking advantage of LINQ but that's not the only way to send queries to the service. Because we're using the data service client framework we can write LINQ queries against the service and the client handles translating the queries into HTTP GETs. But we could also easily specify the raw URI's to send to the service. For instance, when we want to fill a combobox of categories ordered by CategoryName we could do this instead:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.Data.Services.Client&lt;BR&gt;.&lt;BR&gt;.&lt;BR&gt;&lt;SPAN style="COLOR: green"&gt;'Use the untyped DataServiceContext and pass URIs.
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;ctx &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;DataServiceContext(&lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;Uri(&lt;SPAN style="COLOR: #a31515"&gt;"http://localhost:1234/Northwind.svc"&lt;/SPAN&gt;))
&lt;SPAN style="COLOR: green"&gt;'Explicitly execute the the HTTP GET
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;cats = ctx.Execute(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Category)(&lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;Uri(&lt;SPAN style="COLOR: #a31515"&gt;"Categories?$orderby=CategoryName"&lt;/SPAN&gt;, UriKind.Relative))
&lt;SPAN style="COLOR: green"&gt;'Display results in a combobox
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.cboCategoryLookup.ItemsSource = cats.ToList()&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;In the code above the query is explicitly executed on the second line. You can achieve the same response by typing &lt;STRONG&gt;http://localhost:1234/Northwind.svc/Categories?$orderby=CategoryName &lt;/STRONG&gt;in the address bar of your browser.&lt;/P&gt;
&lt;P&gt;However one of the benefits of adding a service reference to our client is that it generates a proxy that inherits from the DataServiceContext that allows typed access to the entity sets that we're exposing from our service. This makes our code cleaner so we can write a LINQ query to do the same job instead:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;WpfClient.NorthwindService&lt;BR&gt;.&lt;BR&gt;.&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;ctx &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;NorthwindEntities(&lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;Uri(&lt;SPAN style="COLOR: #a31515"&gt;"http://localhost:1234/Northwind.svc"&lt;/SPAN&gt;))

&lt;SPAN style="COLOR: green"&gt;'Use LINQ to query the service instead
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;cats = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;c &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;ctx.Categories _
           &lt;SPAN style="COLOR: blue"&gt;Order By &lt;/SPAN&gt;c.CategoryName

&lt;SPAN style="COLOR: green"&gt;'Display results in a combobox. 
'The query is executed when we access the results (calling ToList())
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.cboCategoryLookup.ItemsSource = cats.ToList()&lt;/PRE&gt;
&lt;P&gt;Notice however that there is a subtle difference in this code that you should be aware of. When you write a LINQ query it never executes unless you access the results. In this case we're accessing the results when we call ToList() on the query. This is called deferred execution and it's something to be aware of. But if we look in Fiddler then we can see that the exact same HTTP GET is sent to the service: &lt;STRONG&gt;http://localhost:1234/Northwind.svc/Categories?$orderby=CategoryName &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This also means that not every LINQ query can be translated into an HTTP GET. For instance, what if we just wanted to display a couple properties of the category in the combobox. You would think we'd be able to do something like this:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;cats = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;c &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;ctx.Categories _
           &lt;SPAN style="COLOR: blue"&gt;Order By &lt;/SPAN&gt;c.CategoryName _
           &lt;SPAN style="COLOR: blue"&gt;Select &lt;/SPAN&gt;c.CategoryName, c.Description&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Unfortunately if you try to do this you'll get a NotSupportedException thrown at you by the client framework because it can't translate the query into an HTTP GET. In this case you need to pull down the category entities you want first and then you can project over those to create a list of anonymous types with only the properties you specify. But remember that you need to "execute" the query against the service first and then query over the list that is returned. Here's a way to do this:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;cats = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;c &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;ctx.Categories _
           &lt;SPAN style="COLOR: blue"&gt;Order By &lt;/SPAN&gt;c.CategoryName

&lt;SPAN style="COLOR: green"&gt;'Now project only the properties we want. 
' Call ToList() on the first query to execute the service call
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;results = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;c &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;cats.ToList() _
              &lt;SPAN style="COLOR: blue"&gt;Select &lt;/SPAN&gt;c.CategoryName, c.Description&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;For more details on what is and isn't supported &lt;A href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc907912.aspx"&gt;refer to this article&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Intercepting Queries&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now that we understand how queries work we can start messing with how they execute. :-) Say we want to query only the Products in Northwind that are not Discontinued. We could write the query against our data service that specified the filter like so:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;products = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;ctx.Products _
               &lt;SPAN style="COLOR: blue"&gt;Where &lt;/SPAN&gt;p.Discontinued = &lt;SPAN style="COLOR: blue"&gt;False &lt;/SPAN&gt;_
               &lt;SPAN style="COLOR: blue"&gt;Order By &lt;/SPAN&gt;p.ProductName&lt;/PRE&gt;
&lt;P&gt;Or we could write the raw URI:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;productURI &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;Uri(&lt;SPAN style="COLOR: #a31515"&gt;"Products()?$filter=Discontinued%20eq%20false&amp;amp;$orderby=ProductName"&lt;/SPAN&gt;, _
                          UriKind.Relative)

&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;products = ctx.Execute(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Product)(productURI)&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;But what if it was a new requirement of the entire system that nowhere should we be displaying discontinued products? If this is the case we should be enforcing this on our data service instead. This can be done using &lt;A href="http://msdn.microsoft.com/en-us/library/cc668788.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc668788.aspx"&gt;query interceptors&lt;/A&gt; on the service. The way we create these is we annotate a method on our service with the &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.queryinterceptorattribute.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.queryinterceptorattribute.aspx"&gt;QueryInterceptor attribute&lt;/A&gt;. The method you write must follow these rules:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The method must have public scope and be annotated with the QueryInterceptorAttribute, taking the name of a entity set as a parameter. &lt;/LI&gt;
&lt;LI&gt;The method must accept no parameters. &lt;/LI&gt;
&lt;LI&gt;The method must return an expression of type System.Linq.Expressions.Expression(Of Func(Of T, Boolean)) that is the filter to be composed for the entity set. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The first two requirements are easy the third may be confusing if you've never played with &lt;A href="http://msdn.microsoft.com/en-us/library/bb531253.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb531253.aspx"&gt;lambda expressions&lt;/A&gt;. Basically what happens is you specify additional filtering to apply onto the incoming query via this lambda. So in order to append our condition that we should only be returning products that are not discontinued we can add this method to our data service:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.Data.Services
&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.Linq
&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.ServiceModel.Web
&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.Linq.Expressions

&lt;SPAN style="COLOR: blue"&gt;Public Class &lt;/SPAN&gt;Northwind
    &lt;SPAN style="COLOR: blue"&gt;Inherits &lt;/SPAN&gt;DataService(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;NorthwindEntities)   &lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;    ' This method is called only once to initialize service-wide policies.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Public Shared Sub &lt;/SPAN&gt;InitializeService(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;config &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;IDataServiceConfiguration)
        config.SetEntitySetAccessRule(&lt;SPAN style="COLOR: #a31515"&gt;"Products"&lt;/SPAN&gt;, EntitySetRights.All)
        config.SetEntitySetAccessRule(&lt;SPAN style="COLOR: #a31515"&gt;"Categories"&lt;/SPAN&gt;, EntitySetRights.All)
&lt;SPAN style="COLOR: blue"&gt;    End Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;PRE class=code&gt;&lt;STRONG&gt;    &amp;lt;QueryInterceptor(&lt;SPAN style="COLOR: #a31515"&gt;"Products"&lt;/SPAN&gt;)&amp;gt; _
    &lt;SPAN style="COLOR: blue"&gt;Public Function &lt;/SPAN&gt;FilterProducts() &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Expression(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Func(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Product, &lt;SPAN style="COLOR: blue"&gt;Boolean&lt;/SPAN&gt;))
        &lt;/STRONG&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: green"&gt;'Only return products that are not discontinued
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Return Function&lt;/SPAN&gt;(p) p.Discontinued = &lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;False
    End Function&lt;/STRONG&gt;

End Class&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Now we can write our queries without specifying the additional filter on discontinued and this will not be sent to the service from our client in the HTTP GET but will be executed against our database. The query interceptor will execute regardless if we write a LINQ query or feed it the raw URI.&lt;/P&gt;
&lt;P&gt;LINQ Query:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;products = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;ctx.Products &lt;SPAN style="COLOR: blue"&gt;Order By &lt;/SPAN&gt;p.ProductName
&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.ListView1.ItemsSource = products.ToList()&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;URI:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;productURI &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;Uri(&lt;SPAN style="COLOR: #a31515"&gt;"Products()?$orderby=ProductName"&lt;/SPAN&gt;, UriKind.Relative)
&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;products = ctx.Execute(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Product)(productURI)
&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.ListView1.ItemsSource = products.ToList()&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaQuery1_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaQuery1_2.jpg"&gt;&lt;IMG height=549 alt=AstoriaQuery1 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaQuery1_thumb.jpg" width=644 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaQuery1_thumb.jpg"&gt;&lt;/A&gt; &lt;/PRE&gt;
&lt;P&gt;Pretty slick. You could of course do other processing here first. And you can also specify your own additional &lt;A href="http://msdn.microsoft.com/en-us/library/cc668788.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc668788.aspx"&gt;service operations&lt;/A&gt; as well by attributing them with a &amp;lt;WebGet&amp;gt; attribute. More on those in a later post.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Validation with Change Interceptors&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;You can also add methods to your service that will execute when changes are submitted. This allows us to add validation or other processing onto the data being submitted to the database. You do this by attributing a method in the data service with the &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.services.changeinterceptorattribute.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/system.data.services.changeinterceptorattribute.aspx"&gt;ChangeInterceptor attribute&lt;/A&gt;. A change interceptor will pass the entity being saved and a parameter that indicates what update operation is being performed. For instance, say we want to put a validation on our ProductName so that users cannot submit empty product names to the database. We could write a method in our data service like so:&lt;/P&gt;&lt;PRE class=code&gt;&amp;lt;ChangeInterceptor(&lt;SPAN style="COLOR: #a31515"&gt;"Products"&lt;/SPAN&gt;)&amp;gt; _
&lt;SPAN style="COLOR: blue"&gt;Public Sub &lt;/SPAN&gt;OnChangeProducts(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Product, &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;ops &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;UpdateOperations)
    &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;ops = UpdateOperations.Add &lt;SPAN style="COLOR: blue"&gt;OrElse &lt;/SPAN&gt;ops = UpdateOperations.Change &lt;SPAN style="COLOR: blue"&gt;Then
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'Do not allow products with empty names
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;p.ProductName = &lt;SPAN style="COLOR: #a31515"&gt;"" &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Then
            Throw New &lt;/SPAN&gt;DataServiceException(400, &lt;SPAN style="COLOR: #a31515"&gt;"Product name cannot be empty"&lt;/SPAN&gt;)
        &lt;SPAN style="COLOR: blue"&gt;End If
    End If
End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;When we throw a DataServiceException we can specify the HTTP status code and the message to return to the client. 400 indicates "Bad Request" and we pass the message on what the problem was. So if we try to submit a new or existing product with no product name we will get an HTTP error as seen in Fiddler:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaChange1_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaChange1_2.jpg"&gt;&lt;IMG height=768 alt=AstoriaChange1 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaChange1_thumb.jpg" width=712 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaChange1_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;This is what's happening on the wire when we call SaveChanges and the exception is caught on the client. This prevents our data from being invalid no matter what client it's coming from. However this isn't that user-friendly to say the least. If we're building a smart client it's much better to put this type of validations on the client as well. &lt;/P&gt;
&lt;P&gt;We can do this in our WPF client by extending the Product partial class and implementing IDataErrorInfo and adding our validation. On the WPF client create a new class called Product and place it in the same exact namespace as the NorthwindEntities data service client proxy that is generated for us when we add the service reference. It's called NorthwindService in our case. Then we can overwrite the partial method OnProductNameChanging to do the client-side validation. This method is called from the ProductName property setter in the generated entity on the client. Here's an example of how we can collect validation messages on the Product.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;WpfClient.NorthwindService
&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.ComponentModel

&lt;SPAN style="COLOR: blue"&gt;Namespace &lt;/SPAN&gt;NorthwindService

    &lt;SPAN style="COLOR: blue"&gt;Partial Public Class &lt;/SPAN&gt;Product
        &lt;SPAN style="COLOR: blue"&gt;Implements &lt;/SPAN&gt;IDataErrorInfo

        &lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;OnProductNameChanging(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;value &lt;SPAN style="COLOR: blue"&gt;As String&lt;/SPAN&gt;)
            &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;value &lt;SPAN style="COLOR: blue"&gt;Is Nothing OrElse &lt;/SPAN&gt;value.Trim = &lt;SPAN style="COLOR: #a31515"&gt;"" &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Then
                Me&lt;/SPAN&gt;.AddError(&lt;SPAN style="COLOR: #a31515"&gt;"ProductName"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Product name cannot be empty"&lt;/SPAN&gt;)
            &lt;SPAN style="COLOR: blue"&gt;Else
                Me&lt;/SPAN&gt;.RemoveError(&lt;SPAN style="COLOR: #a31515"&gt;"ProductName"&lt;/SPAN&gt;)
            &lt;SPAN style="COLOR: blue"&gt;End If
        End Sub

#Region &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;"IDataErrorInfo Members"
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;m_validationErrors &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;Dictionary(&lt;SPAN style="COLOR: blue"&gt;Of String&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;String&lt;/SPAN&gt;)

        &lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;AddError(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;columnName &lt;SPAN style="COLOR: blue"&gt;As String&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;msg &lt;SPAN style="COLOR: blue"&gt;As String&lt;/SPAN&gt;)
            &lt;SPAN style="COLOR: blue"&gt;If Not &lt;/SPAN&gt;m_validationErrors.ContainsKey(columnName) &lt;SPAN style="COLOR: blue"&gt;Then
                &lt;/SPAN&gt;m_validationErrors.Add(columnName, msg)
            &lt;SPAN style="COLOR: blue"&gt;End If
        End Sub

        Private Sub &lt;/SPAN&gt;RemoveError(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;columnName &lt;SPAN style="COLOR: blue"&gt;As String&lt;/SPAN&gt;)
            &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;m_validationErrors.ContainsKey(columnName) &lt;SPAN style="COLOR: blue"&gt;Then
                &lt;/SPAN&gt;m_validationErrors.Remove(columnName)
            &lt;SPAN style="COLOR: blue"&gt;End If
        End Sub

        Friend ReadOnly Property &lt;/SPAN&gt;HasErrors() &lt;SPAN style="COLOR: blue"&gt;As Boolean
            Get
                Return &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.Error &lt;SPAN style="COLOR: blue"&gt;IsNot Nothing&lt;/SPAN&gt;)
            &lt;SPAN style="COLOR: blue"&gt;End Get
        End Property

        Friend ReadOnly Property &lt;/SPAN&gt;[Error]() &lt;SPAN style="COLOR: blue"&gt;As String _&lt;BR&gt;                                 Implements &lt;/SPAN&gt;System.ComponentModel.IDataErrorInfo.Error
            &lt;SPAN style="COLOR: blue"&gt;Get
                If &lt;/SPAN&gt;m_validationErrors.Count &amp;gt; 0 &lt;SPAN style="COLOR: blue"&gt;Then
                    Return &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;"Product Data is invalid"
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Else
                    Return Nothing
                End If
            End Get
        End Property

        Default Friend ReadOnly Property &lt;/SPAN&gt;Item(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;columnName &lt;SPAN style="COLOR: blue"&gt;As String&lt;/SPAN&gt;) &lt;SPAN style="COLOR: blue"&gt;As String _&lt;BR&gt;                                         Implements &lt;/SPAN&gt;System.ComponentModel.IDataErrorInfo.Item
            &lt;SPAN style="COLOR: blue"&gt;Get
                If &lt;/SPAN&gt;m_validationErrors.ContainsKey(columnName) &lt;SPAN style="COLOR: blue"&gt;Then
                    Return &lt;/SPAN&gt;m_validationErrors(columnName).ToString
                &lt;SPAN style="COLOR: blue"&gt;Else
                    Return Nothing
                End If
            End Get
        End Property
#End Region

    End Class
&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;End Namespace&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Notice that the client-side IDataErrorInfo properties are declared as Friend (internal) so that they are not serialized back up to the server. Next we need to make sure the bindings in the XAML of our ProductDetail form is set up to display the error. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox 
&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt; Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=ProductName, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;&lt;STRONG&gt;ValidatesOnDataErrors&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;=True&lt;/STRONG&gt;}"
&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt; Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="TextBox1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="180" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" /&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;You can also add a validation ErrorTemplate if you like. &lt;A href="http://blogs.msdn.com/bethmassi/archive/2008/06/27/displaying-data-validation-messages-in-wpf.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2008/06/27/displaying-data-validation-messages-in-wpf.aspx"&gt;I've shown this validation technique with WPF here before&lt;/A&gt;. So when we don't enter the ProductName on a product we can display the problem to the user right away without bothering our data service:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaChange2_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaChange2_2.jpg"&gt;&lt;IMG height=352 alt=AstoriaChange2 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaChange2_thumb.jpg" width=488 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesInterceptingQueriesan_C65B/AstoriaChange2_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Check out the &lt;A href="http://code.msdn.microsoft.com/astoriawpf" target=_blank&gt;updated sample on Code Galley&lt;/A&gt;, in there I also implement IEditableObject so that users can cancel out of editing of the products.&lt;/P&gt;
&lt;P&gt;However, the fact that we have to put rules in two locations in our code is a total drag. If we could type share the entity partial classes on the server and the client then we could write this code in one place and run it in both the client and the server. This is why if you have complex business rules you're probably better off creating your own DataContracts and implementing your own WCF services. However, applications like this that have simple validation and heavy CRUD requirements make it a perfect candidate to use ADO.NET Data Services.&lt;/P&gt;
&lt;P&gt;Next post I'll show how we can query and edit tabular data inside of an Excel client and post changes back to the data service. &lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9362890" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Visual+Basic/default.aspx">Visual Basic</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Data/default.aspx">Data</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/N-tier/default.aspx">N-tier</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Entity+Framework/default.aspx">Entity Framework</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>ADO.NET Data Services - Enforcing FK Associations and a Fix for Deleting Entities</title><link>http://blogs.msdn.com/bethmassi/archive/2009/01/20/ado-net-data-services-enforcing-fk-associations-and-a-fix-for-deleting-entities.aspx</link><pubDate>Wed, 21 Jan 2009 06:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9354286</guid><dc:creator>Beth Massi</dc:creator><slash:comments>17</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9354286.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9354286</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9354286</wfw:comment><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/15/ado-net-data-services-building-a-wpf-client.aspx" target="_blank"&gt;Last post&lt;/a&gt; I described one way to build a smart client in WPF against ADO.NET Data Services. &lt;a href="http://code.msdn.microsoft.com/astoriawpf/" target="_blank"&gt;In this example&lt;/a&gt; we are editing the products table and associating them to categories in the categories table from Northwind. In the Northwind database the CategoryID on the Products table allows nulls so that you can have products that do not necessarily belong to a category. More common, however, are associations that are &lt;strong&gt;required&lt;/strong&gt; and enforced by not allowing nulls in the foreign keys in the database. If we make a change to our Northwind data model to enforce this we will encounter errors when we try to save the data back to the service. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Enforcing Foreign Key Constraints&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Let me show you what I mean by changing the example to enforce that products belong to a category. Open up the Northwind data model in the designer and select the FK_Products_Categories association and change the multiplicity property on the category end to 1 (One) and then save the model and build the service. Then make sure to update the service reference on the client and rebuild again (under the client project expand Service References then right-click on the reference and choose Update Reference).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ImportantFixforADO.NETDataServices_AD73/AstoriaFix1_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="352" alt="AstoriaFix1" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ImportantFixforADO.NETDataServices_AD73/AstoriaFix1_thumb.jpg" width="709" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If we tried to use the original code sample against this new data model we would have problems. When we run the client and make a change to a product and associate a new category we would get the error: &lt;em&gt;A relationship is being added or deleted from an AssociationSet 'FK_Products_Categories'. With cardinality constraints, a corresponding 'Products' must also be added or deleted. &lt;/em&gt;This is a problem because the Data Services client was trying to delete the link to the category on the product first and then update the product after that. &lt;/p&gt;  &lt;p&gt;If we tried to add a new product it would have also failed: &lt;em&gt;Entities in 'NorthwindEntities.Products' participate in the 'FK_Products_Categories' relationship. 0 related 'Categories' were found. 1 'Categories' is expected. &lt;/em&gt;This is a problem because the client data service is attempting to add a new product with no associated category (if you look in the request header you will not see the category reference). Now that we've changed the model these situations are not allowed so they fail. &lt;/p&gt;  &lt;p&gt;In order to fix them I had to make a couple code changes. First we need to change how we were setting the category association. Instead of calling DeleteLink and AddLink on the Category entity we need to call SetLink on the Product entity instead. In fact, this will work regardless if we are enforcing the association exist or not so it's best to use this when setting 1..1 associations (and it makes a lot more sense to me as well). Because of this I &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/01/15/ado-net-data-services-building-a-wpf-client.aspx" target="_blank"&gt;updated the previous post&lt;/a&gt; and the &lt;a href="http://code.msdn.microsoft.com/astoriawpf/" target="_blank"&gt;code sample on code gallery&lt;/a&gt; with this new code. So when we edit our Product we need to change our code to this:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;p &lt;span style="color: blue"&gt;As &lt;/span&gt;Product = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.ProductView.CurrentItem(), Product)
&lt;span style="color: blue"&gt;If &lt;/span&gt;p &lt;span style="color: blue"&gt;IsNot Nothing Then&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;    Dim &lt;/span&gt;frm &lt;span style="color: blue"&gt;As New &lt;/span&gt;ProductDetail()
    frm.Product = p
    frm.CategoryList = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.CategoryLookup
&lt;span style="color: blue"&gt;    Dim &lt;/span&gt;oldCategory = p.Category

&lt;span style="color: blue"&gt;    If &lt;/span&gt;frm.ShowDialog() &lt;span style="color: blue"&gt;Then &lt;span style="color: green"&gt;'changes were made &lt;/span&gt;
        &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;newCategory = p.Category

        &lt;span style="color: green"&gt;'If the category was changed, set the new link
        ' then set the product state to updated
        &lt;/span&gt;&lt;span style="color: blue"&gt;With Me&lt;/span&gt;.DataServiceClient
            &lt;span style="color: blue"&gt;If &lt;/span&gt;(newCategory &lt;span style="color: blue"&gt;IsNot &lt;/span&gt;oldCategory) &lt;span style="color: blue"&gt;Then

              &lt;strong&gt;  &lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;.SetLink(p, &lt;span style="color: #a31515"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;, newCategory)&lt;/strong&gt;

                &lt;span style="color: green"&gt;'This will not work if we are enforcing the FK to 
                ' Category from Product. Use SetLink instead&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green"&gt;                '.DeleteLink(oldCategory, &amp;quot;Products&amp;quot;, p)
                '.AddLink(newCategory, &amp;quot;Products&amp;quot;, p)
            &lt;/span&gt;&lt;span style="color: blue"&gt;End If
            &lt;/span&gt;.UpdateObject(p)
        &lt;span style="color: blue"&gt;End With
.&lt;br /&gt;.&lt;br /&gt;.
&lt;/span&gt;&lt;font color="#0000ff"&gt;&lt;/font&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/pre&gt;

&lt;p&gt;When we add new Products we also need to call SetLink after we add the new Product:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: green"&gt;'Add a new Product to the List
&lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;p &lt;span style="color: blue"&gt;As &lt;/span&gt;Product = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.ProductView.AddNew(), Product)
p.ProductName = &lt;span style="color: #a31515"&gt;&amp;quot;New Product&amp;quot;
&lt;/span&gt;
&lt;span style="color: green"&gt;'Create our detail form and setup the data 
&lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;frm &lt;span style="color: blue"&gt;As New &lt;/span&gt;ProductDetail()
frm.Product = p
frm.CategoryList = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.CategoryLookup

&lt;span style="color: blue"&gt;If &lt;/span&gt;frm.ShowDialog() &lt;span style="color: blue"&gt;Then &lt;/span&gt;&lt;span style="color: green"&gt;'OK
&lt;/span&gt;&lt;span style="color: blue"&gt;    Me&lt;/span&gt;.ProductView.CommitNew()
    &lt;span style="color: blue"&gt;Dim &lt;/span&gt;newCategory = p.Category

    &lt;span style="color: green"&gt;'Add a new product and set the association to the parent Category
    &lt;/span&gt;&lt;span style="color: blue"&gt;With Me&lt;/span&gt;.DataServiceClient
       .AddToProducts(p)
       &lt;strong&gt;.SetLink(p, &lt;span style="color: #a31515"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;, newCategory)&lt;/strong&gt;

       &lt;span style="color: green"&gt;'This will not work if we are enforcing the FK to 
       ' Category from Product. Use SetLink instead
       '.AddLink(newCategory, &amp;quot;Products&amp;quot;, p)
   &lt;/span&gt;&lt;span style="color: blue"&gt;End With&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The rule of thumb is AddLink is used when we are modifying the 1...many or many...many relationships on an entity and SetLink is used to modify a 1..1 relationship as in the case of our example. &lt;a href="http://blogs.msdn.com/phaniraj/archive/2008/07/02/working-with-relations-in-ado-net-data-services-beta-1.aspx" target="_blank"&gt;Check out this blog post&lt;/a&gt; which should help clear up when to use SetLink versus AddLink. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deleting Entities Involved in an Association&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You may have issues deleting entities that are involved in an association (regardless of whether they are enforced or not). This was a bug in ADO.NET Data Services described in &lt;a href="http://support.microsoft.com/kb/958484/" target="_blank"&gt;KB958484&lt;/a&gt; and is fixed with &lt;a href="http://support.microsoft.com/kb/959209/" target="_blank"&gt;this update&lt;/a&gt;. (This should be flowing along with your regularly scheduled Windows Updates but you may not have gotten it yet so if you're experiencing this issue make sure you &lt;a href="http://support.microsoft.com/kb/959209/" target="_blank"&gt;install this fix&lt;/a&gt;.)&amp;#160; In our example I was forced to detach the category object from the client context before submitting the deletes. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;p &lt;span style="color: blue"&gt;As &lt;/span&gt;Product = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.ProductView.CurrentItem(), Product)
&lt;span style="color: blue"&gt;If &lt;/span&gt;p &lt;span style="color: blue"&gt;IsNot Nothing Then&lt;br /&gt;
    With Me&lt;/span&gt;.DataServiceClient
       &lt;strong&gt; .Detach(p.Category)&lt;/strong&gt;
        .DeleteObject(p)
    &lt;span style="color: blue"&gt;End With

    Me&lt;/span&gt;.ProductView.Remove(p)
&lt;span style="color: blue"&gt;End If&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Unfortunately this has side effects when working in batch like we've set up on our form. If I then added or edited another product but chose the same category that was on a product that I deleted, then I would get an InvalidOperationException on the client: &lt;em&gt;The context is not currently tracking the entity. &lt;/em&gt;This is because I detached the category when I shouldn't have. But if I don't detach the category before deleting the product then I get another error, this time an XMLException: &lt;em&gt;Root element is missing. &lt;/em&gt;Note, that if we didn't bring down the associated category for each product then this would work fine. It only happens when we have an association. &lt;/p&gt;

&lt;p&gt;Once you &lt;a href="http://support.microsoft.com/kb/959209/" target="_blank"&gt;install the update&lt;/a&gt; this bug will be fixed and the correct code should be to just call .DeleteObject:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;    With Me&lt;/span&gt;.DataServiceClient
       .DeleteObject(p)
    &lt;span style="color: blue"&gt;End With&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;This means that we can enable batching and add/update/delete products at will and submit them all at once in one call. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Try
&lt;/span&gt;&lt;span style="color: green"&gt;    'Batching will wrap all changes submitted into a transaction
    &lt;/span&gt;&lt;span style="color: blue"&gt;Me&lt;/span&gt;.DataServiceClient.SaveChanges(&lt;strong&gt;System.Data.Services.Client.SaveChangesOptions.Batch&lt;/strong&gt;)
    MsgBox(&lt;span style="color: #a31515"&gt;&amp;quot;Your data was saved&amp;quot;&lt;/span&gt;)
&lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
    MsgBox(ex.ToString())
&lt;span style="color: blue"&gt;End Try&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Notice that when we batch save our changes we also get a database transaction. In your own applications you should determine if the set of data you are submitting to the server should be wrapped in a transaction or not (click image to enlarge). &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ImportantFixforADO.NETDataServices_AD73/AstoriaFix2_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="414" alt="AstoriaFix2" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ImportantFixforADO.NETDataServices_AD73/AstoriaFix2_thumb.jpg" width="708" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Products aren't reliant on each other so in this example it's probably overkill. You should evaluate your sets of data carefully to ensure the right level of isolation is needed. &lt;a href="http://code.msdn.microsoft.com/astoriawpf/" target="_blank"&gt;I updated the sample on Code Gallery&lt;/a&gt; for you to play with. &lt;/p&gt;

&lt;p&gt;You may be asking &amp;quot;Why doesn't the data services client do all this association linking for me automatically?&amp;quot; The reason I've gleaned from a few folks is that the team wanted the framework to be very simple and work with POCO (Plain Old CLR Objects) with no extra overhead. That said, there is a line of practicality here so they are looking into extending this in future versions. I'd like to also see the ability to extend the entities and add additional business functionality and properties not backed by database fields to them as well. That would make ADO.NET Data Services my data access layer of choice for general purpose n-tier smart client business applications. &lt;/p&gt;

&lt;p&gt;Okay, so now that we have CRUD working properly in all our scenarios in the next post (soon) I'll show how we can intercept queries and change operations in order to do some additional processing -- I know I said that last post but this time I mean it ;-).&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9354286" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Data/default.aspx">Data</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/N-tier/default.aspx">N-tier</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Entity+Framework/default.aspx">Entity Framework</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>ADO.NET Data Services - Building a WPF Client</title><link>http://blogs.msdn.com/bethmassi/archive/2009/01/15/ado-net-data-services-building-a-wpf-client.aspx</link><pubDate>Fri, 16 Jan 2009 07:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9324201</guid><dc:creator>Beth Massi</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9324201.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9324201</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9324201</wfw:comment><description>&lt;P&gt;&lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx"&gt;In my last post I introduced ADO.NET Data Services&lt;/A&gt; and how you can easily expose your data model via RESTful services that support the basic CRUD (Create,Retrieve,Update,Delete) operations. Basic CRUD database operations map well to the familiar HTTP verbs POST, GET, MERGE, DELETE and the framework takes care of the plumbing for us. In this post I'm going to build a simple WPF client that shows how to work with the client piece of the framework which resides in the System.Data.Service.Client namespace.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The ADO.NET Data Service&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Based on the &lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx"&gt;previous example&lt;/A&gt;, our data service exposes the Northwind data model that I created as an Entity Data Model generated from the database. The only thing I've done to the Entity Model is I've changed the Categories navigation property on the Product to singular (since a product can only have one category) as well as the names of the entities themselves and the entity sets to plural like so:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF1_6.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF1_6.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=319 alt=AstoriaWPF1 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF1_thumb_2.jpg" width=612 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF1_thumb_2.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;We're going to build a client that allows us to do CRUD operations on the Products data so I'm going to allow full access to that entity set. And since products must belong to a category in Northwind, we need to be able to associate them when we are editing the products. Therefore I'll need to retrieve a list of categories for our lookup list so I've enabled read access on the Categories entity set. So here's what our data service looks like in the Northwind.svc:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.Data.Services
&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.Linq
&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.ServiceModel.Web

&lt;SPAN style="COLOR: blue"&gt;Public Class &lt;/SPAN&gt;Northwind
    &lt;SPAN style="COLOR: blue"&gt;Inherits &lt;/SPAN&gt;DataService(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;NorthwindEntities)

    &lt;SPAN style="COLOR: green"&gt;' This method is called only once to initialize service-wide policies.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Public Shared Sub &lt;/SPAN&gt;InitializeService(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;config &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;IDataServiceConfiguration)
        config.SetEntitySetAccessRule(&lt;SPAN style="COLOR: #a31515"&gt;"Products"&lt;/SPAN&gt;, EntitySetRights.All)
        config.SetEntitySetAccessRule(&lt;SPAN style="COLOR: #a31515"&gt;"Categories"&lt;/SPAN&gt;, EntitySetRights.AllRead)
        &lt;SPAN style="COLOR: green"&gt;' Return verbose errors to help in debugging&lt;/SPAN&gt;
        config.UseVerboseErrors = &lt;SPAN style="COLOR: blue"&gt;True
    End Sub
&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;End Class&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Simple stuff. Next I'm going to add a new project to the solution and select WPF application. Then we need to add a Service Reference to the data service exactly how I showed in the &lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx"&gt;previous post&lt;/A&gt; when I created the client console application in that example. This step will add a reference to the client framework (System.Data.Services.Client) as well as generate the proxy code for our model. &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF2_4.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF2_4.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=374 alt=AstoriaWPF2 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF2_thumb_1.jpg" width=253 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF2_thumb_1.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;This is something to be aware of. At this time ADO.NET Data Services cannot type share the entities so you end up having client types and server types. Because of this, ADO.NET Data Services are not meant to replace a real business object layer (yet). So if you have complex business rules you want to share on the client and server you are better off writing your own WCF services and data contracts. However, if you have simple CRUD and validation requirements or are looking for a remote data access layer for applications where business rules and validations are processed predominantly on the server (like web or reporting or query-heavy applications) then ADO.NET Data Services are a great fit. And no one is stopping you from using both your own WCF services in addition to ADO.NET data services in your client applications. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Building the WPF Client&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now it's time to build out some UI. We're going to have two forms, one for displaying the list of products by category which will allow you to modify them and another form that will open when editing or adding the product details. First let's build the ProductList form. I want to make the user pick a category before I pull down the products so I've got a combobox I'll need to populate with the list of categories available and a search button to execute the query to the data service. Under that I have a ListBox with it's View set to a GridView and I've defined the binding to a few of the product properties to show up in the columns. Under that is the buttons we'll use to make changes to the data; Edit, Add, Delete and Save. Here's the XAML &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Class&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="ProductList"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Title&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Northwind Traders" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="385" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="533" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="ProductList"&amp;gt;
&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.RowDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;RowDefinition &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="50*" /&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;RowDefinition &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="198*" /&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;RowDefinition &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="44*" /&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.RowDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView 
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ItemsSource&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;}"
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;IsSynchronizedWithCurrentItem&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="True" 
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Row&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="ListView1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,4,0,0"&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView.View&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridView&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
                &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Header&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Product Name" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="200" 
                          &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=ProductName}" /&amp;gt;
                &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Header&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Category" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="150" 
                          &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=Category.CategoryName}" /&amp;gt;
                &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Header&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Price" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="70" 
                          &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=UnitPrice, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;='c2'}" /&amp;gt;
                &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridViewColumn &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Header&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Units" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="70"  
                          &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberBinding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=UnitsInStock, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;StringFormat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;='n0'}" /&amp;gt;
            &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GridView&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
      &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView.View&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ListView&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GroupBox &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Header&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Search Products" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,3,0" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="GroupBox1" &amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ComboBox &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="90,6,199,0" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="26" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Top" 
                      &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="cboCategoryLookup"  &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="CategoryName" 
                      &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;IsSynchronizedWithCurrentItem&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="True" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" 
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="6,6,0,0" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Label1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="78" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="26" 
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Top"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Category:&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,5.98,132,0" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="64" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="26" 
                    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Top"
                    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="btnSearch" &amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Search&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;GroupBox&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="btnAdd" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,143,12" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="64" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Row&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="2" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="26" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Bottom" &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Add&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="btnDelete" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,73,12" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="64" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Row&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="2" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="26" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Bottom" &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Delete&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="btnEdit" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,213,12" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="64" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Row&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="2"  &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="26" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Bottom" &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Edit&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="btnSave" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,3,12" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="64" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Row&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="2" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="26" 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Bottom" &amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Save&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Notice how we set up the binding to display the category for the product. Each product has a parent category that is accessed through the Category navigation property on the Product entity as defined in our Entity Data Model. This is how we traverse the association so that we can get at the CategoryName on the category entity that is associated with the product. &lt;/P&gt;
&lt;P&gt;Before we can write our queries against our data service we will need to set up a few class-level variables to keep track of the data service client proxy, the list of products and categories and the products' CollectionView. Note that you need to supply the URI to the service when you create the instance of the client proxy. (I've hard-coded it here for clarity but in a real app this should be in your My.Settings so that you can change it after deployment.) &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;WpfClient.MyDataServiceReference

&lt;SPAN style="COLOR: blue"&gt;Class &lt;/SPAN&gt;ProductList&lt;BR&gt;&lt;SPAN style="COLOR: green"&gt;
   &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;DataServiceClient &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;NorthwindEntities(&lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;Uri(&lt;SPAN style="COLOR: #a31515"&gt;"http://localhost:1234/Northwind.svc"&lt;/SPAN&gt;))
   &lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;Products &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;List(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Product)
   &lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;CategoryLookup &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;List(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Category)
   &lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;ProductView &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;ListCollectionView   &lt;/PRE&gt;
&lt;P&gt;&lt;STRONG&gt;Querying the Data Service Using LINQ&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now we can write some code in our Loaded event handler to query the list of categories from our data service and populate the Category combobox. We can write a LINQ query over the DataServiceClient proxy and it will handle translating the call to the RESTful data service. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;Window1_Loaded() &lt;SPAN style="COLOR: blue"&gt;Handles MyBase&lt;/SPAN&gt;.Loaded&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;    'Grab the list of categories and populate the combobox&lt;/SPAN&gt;
    &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.CategoryLookup = (&lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;c &lt;SPAN style="COLOR: blue"&gt;In Me&lt;/SPAN&gt;.DataServiceClient.Categories _
                         &lt;SPAN style="COLOR: blue"&gt;Order By &lt;/SPAN&gt;c.CategoryName).ToList()

    &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.cboCategoryLookup.ItemsSource = &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.CategoryLookup
    &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.cboCategoryLookup.SelectedIndex = 0
&lt;SPAN style="COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Let's open up Fiddler and SQL Profiler and see what happens when we run it. (Note: to run localhost web calls through Fiddler I changed the URI to http://&lt;STRONG&gt;ipv4.fiddler:&lt;/STRONG&gt;1234/Northwind.svc. &lt;A href="http://www.fiddlertool.com/Fiddler/help/hookup.asp#Q-LocalTraffic" target=_blank mce_href="http://www.fiddlertool.com/Fiddler/help/hookup.asp#Q-LocalTraffic"&gt;See this page for details&lt;/A&gt;.)&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF3_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF3_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=463 alt=AstoriaWPF3 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF3_thumb.jpg" width=692 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF3_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;What we're looking at&amp;nbsp;is our form with the categories ordered by their name. Then we have Fiddler showing the HTTP Get request header and the RSS Atom feed response containing the categories. Notice how the LINQ query is automatically translated to the GET /Northwind.svc/Categories()?$orderby=CategoryName and passed as a query against our IQueryable Entity Data Model. The Entity Framework handles the communication to SQL Server. You can see the SQL query in SQL Profiler. &lt;/P&gt;
&lt;P&gt;It's important to note that since LINQ queries on the client need to be translated to HTTP GETs by the framework not every extension method you see available in IntelliSense will work. It also may be impossible to write complex sub-queries. In those cases you may need to write a simpler queries, convert them to in-memory collections like a List and then write additional queries over the in-memory collections. Take a look at the middle of &lt;A href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc907912.aspx"&gt;this article&lt;/A&gt; for a list of supported operations.&lt;/P&gt;
&lt;P&gt;Now that we have the list of Categories to choose from we can handle the Search button's click event and write the query to bring down the related Products. Since we want to be able to edit their details, including associating a parent Category, we need to explicitly load the Category property on the Product entity which is a reference to the parent Category entity. We then populate a simple List with the results and set up the binding on the form by setting the Window's DataContext.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;btnSearch_Click() &lt;SPAN style="COLOR: blue"&gt;Handles &lt;/SPAN&gt;btnSearch.Click
&lt;SPAN style="COLOR: green"&gt;    'Get the selected category from the combobox
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    Dim &lt;/SPAN&gt;category = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.cboCategoryLookup.SelectedItem, Category)

&lt;SPAN style="COLOR: green"&gt;    'Return all the products for that category ordered by ProductName
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    Dim &lt;/SPAN&gt;results = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;In Me&lt;/SPAN&gt;.DataServiceClient.Products.Expand(&lt;SPAN style="COLOR: #a31515"&gt;"Category"&lt;/SPAN&gt;) _
                  &lt;SPAN style="COLOR: blue"&gt;Order By &lt;/SPAN&gt;p.ProductName _
                  &lt;SPAN style="COLOR: blue"&gt;Where &lt;/SPAN&gt;p.Category.CategoryID = category.CategoryID

&lt;SPAN style="COLOR: green"&gt;    'Populate the Products list 
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    Me&lt;/SPAN&gt;.Products = &lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;List(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Product)(results)
&lt;SPAN style="COLOR: green"&gt;    'Set the DataContext of the Window so controls will bind to the data
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    Me&lt;/SPAN&gt;.DataContext = &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.Products
&lt;SPAN style="COLOR: green"&gt;    'Grab the CollectionView so that we can use it to add and remove items from the list
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    Me&lt;/SPAN&gt;.ProductView = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(CollectionViewSource.GetDefaultView(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.DataContext), ListCollectionView)&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;The .Expand("Category") syntax above is what loads the parent Category entity onto the Product. Now when we run the form and hit the Search button the list of Products is populated.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF4_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF4_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=483 alt=AstoriaWPF4 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF4_thumb.jpg" width=701 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF4_thumb.jpg"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Creating the Product Detail Form&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now we need to create a form that will allow us to edit or add the details of a Product. We're going to call this form up from the Edit and Add buttons at the bottom of the ProductList form. I've created a simple one that has a couple stack panels, one with labels and one with the data bound controls, and an OK and Cancel button. Here's the XAML:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Class&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="ProductDetail"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Title&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Product Details" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="318" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="353"&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.RowDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;RowDefinition &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="243*" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;RowDefinition &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="42*" /&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.RowDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.ColumnDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ColumnDefinition &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="114*" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ColumnDefinition &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="218*" /&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.ColumnDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="StackPanel1"&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Label1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto" 
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Product Name:&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Label2" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto" 
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Category:&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Label3" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto" 
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Quantity per Unit:&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Label4" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto" 
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Unit Price:&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Label5" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto" 
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Units in Stock:&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Label6" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto" 
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Units on Order:&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Label7" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Auto" 
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Reorder Level:&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Column&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="StackPanel2"&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=ProductName}"
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="TextBox1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="180" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ComboBox 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="cboCategoryLookup" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="180" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;IsEditable&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="False" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;DisplayMemberPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="CategoryName" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;SelectedValuePath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="CategoryID"
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;SelectedValue&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=Category.CategoryID, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Mode&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=OneWay}"/&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=QuantityPerUnit}"
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="TextBox2" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="180" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=UnitPrice}"
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="TextBox3" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="84" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=UnitsInStock}"
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="TextBox4" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="84" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=UnitsOnOrder}"
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="TextBox5" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="84" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=ReorderLevel}"
                  &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="TextBox6" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="84" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;CheckBox 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;IsChecked&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=Discontinued}"
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="16" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="CheckBox1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="120" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="3"&amp;gt;
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Discontinued?
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;CheckBox&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="btnOK" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;IsDefault&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="True"
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Column&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Row&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1"  
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="76" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="26" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,81.627,4" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Bottom" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right" &amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;OK&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="btnCancel" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;IsCancel&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="True" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Column&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Grid.Row&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="76" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="26" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0,0,0,4" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Bottom" 
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Right"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Cancel&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Note the binding syntax on the category lookup in the XAML above. The &lt;STRONG&gt;DisplayMemberPath="CategoryName" SelectedValuePath="CategoryID"&lt;/STRONG&gt; are fairly straight-forward. The DisplayMemberPath is set to the field on the items in the combobox that we want to display to the user. The SelectedValuePath is set to the field on the items in the combobox that is used to set the value on the Product. To set up the list of items to display in the combobox we will set the ItemsSource property to a List(Of Category) in code. It's on these Category objects where we are indicating the properties to use for display and selection. If we were using DataSets or LINQ to SQL classes the SelectedValuePath would match up with the CategoryID foreign key field in the Product. However since the Entity Data Model uses object associations instead of ID properties, normal data binding won't get us all the way there. &lt;/P&gt;
&lt;P&gt;Therefore SelectedValue="{Binding Path=Category.CategoryID, Mode=OneWay}" is specified to indicate to traverse the Category navigation property over to the Category entity hanging off the Product and to match &lt;EM&gt;that &lt;/EM&gt;CategoryID to the CategoryID on the list of categories in the combobox. This gets the right category to display when we open the form. Notice however the Mode is set to OneWay. If we don't specify this, then when we select a new Category in the combobox, only the CategoryID on the related entity would change and NOT the reference itself which is what we need. (I'm thinking this should be possible in WPF to set the Product.Category value to a Category object in XAML but it escapes me.) Therefore we need to set it in code when we close the form. The code is a lot shorter than my explanation of the code ;-):&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;WpfClient.MyDataServiceReference

&lt;SPAN style="COLOR: blue"&gt;Partial Public Class &lt;/SPAN&gt;ProductDetail

    &lt;SPAN style="COLOR: green"&gt;'This is the Product we are editing and is 
    ' set from the calling form.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;_product &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Product
    &lt;SPAN style="COLOR: blue"&gt;Public Property &lt;/SPAN&gt;Product() &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Product
        &lt;SPAN style="COLOR: blue"&gt;Get
            Return &lt;/SPAN&gt;_product
        &lt;SPAN style="COLOR: blue"&gt;End Get
        Set&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;value &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Product)
            _product = value
            &lt;SPAN style="COLOR: green"&gt;'Binds the controls to this product
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.DataContext = _product
        &lt;SPAN style="COLOR: blue"&gt;End Set
    End Property

    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'This is the same list of categories
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;_categoryList &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;List(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Category)
    &lt;SPAN style="COLOR: blue"&gt;Public Property &lt;/SPAN&gt;CategoryList() &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;List(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Category)
        &lt;SPAN style="COLOR: blue"&gt;Get
            Return &lt;/SPAN&gt;_categoryList
        &lt;SPAN style="COLOR: blue"&gt;End Get
        Set&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;value &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;List(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Category))
            _categoryList = value
            &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.cboCategoryLookup.ItemsSource = _categoryList
        &lt;SPAN style="COLOR: blue"&gt;End Set
    End Property

    Private Sub &lt;/SPAN&gt;btnOK_Click() &lt;SPAN style="COLOR: blue"&gt;Handles &lt;/SPAN&gt;btnOK.Click
        &lt;SPAN style="COLOR: green"&gt;'Manually associate the selected Category with the Product.Category property
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.Product.Category = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.cboCategoryLookup.SelectedItem, Category)
        &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.DialogResult = &lt;SPAN style="COLOR: blue"&gt;True
        Me&lt;/SPAN&gt;.Close()
    &lt;SPAN style="COLOR: blue"&gt;End Sub
End Class&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;&lt;STRONG&gt;Adding New Products&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now that we have our forms designed and our data binding set up let's get back to the good stuff. First we need to hook up the Add button back on our ProductList form. Since we are working with a single reference to the data service client proxy it's already attached to the objects that we've retrieved. Working with a single reference also allows us to send batch update requests to the service (more on that in a minute). Here's the code for our Add button's click event handler:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;btnAdd_Click() &lt;SPAN style="COLOR: blue"&gt;Handles &lt;/SPAN&gt;btnAdd.Click

    &lt;SPAN style="COLOR: green"&gt;'Add a new Product to the List
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Product = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.ProductView.AddNew(), Product)
    p.ProductName = &lt;SPAN style="COLOR: #a31515"&gt;"New Product"
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.ListView1.ScrollIntoView(p)

    &lt;SPAN style="COLOR: green"&gt;'Create our detail form and setup the data 
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;frm &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;ProductDetail()
    frm.Product = p
    frm.CategoryList = &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.CategoryLookup

    &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;frm.ShowDialog() &lt;SPAN style="COLOR: blue"&gt;Then &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'OK
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.ProductView.CommitNew()
        &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;newCategory = p.Category

&lt;SPAN style="COLOR: green"&gt;        'Add a new product and set the association to the parent Category
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;With Me&lt;/SPAN&gt;.DataServiceClient
            .AddToProducts(p)
            .SetLink(p, &lt;SPAN style="COLOR: #a31515"&gt;"Category"&lt;/SPAN&gt;, newCategory)
        &lt;SPAN style="COLOR: blue"&gt;End With
&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;
        'Refresh the grid 
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.DataContext = &lt;SPAN style="COLOR: blue"&gt;Nothing
        Me&lt;/SPAN&gt;.DataContext = &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.Products
    &lt;SPAN style="COLOR: blue"&gt;Else &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'Cancel - remove the new product from the list
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.ProductView.CancelNew()
    &lt;SPAN style="COLOR: blue"&gt;End If

End Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Now we can Add new products to the list:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF5_4.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF5_4.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=393 alt=AstoriaWPF5 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF5_thumb_1.jpg" width=540 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF5_thumb_1.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Notice that we're not actually saving anything yet in the code above -- we won't hit the data service again until the user clicks Save. So in order to see if this works and what the call to add a product looks like on the wire, let's hook up our Save button -- it's very simple:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;    Private Sub &lt;/SPAN&gt;btnSave_Click() &lt;SPAN style="COLOR: blue"&gt;Handles &lt;/SPAN&gt;btnSave.Click
        &lt;SPAN style="COLOR: blue"&gt;Try
            Me&lt;/SPAN&gt;.DataServiceClient.SaveChanges()
            MsgBox(&lt;SPAN style="COLOR: #a31515"&gt;"Your data was saved"&lt;/SPAN&gt;)
        &lt;SPAN style="COLOR: blue"&gt;Catch &lt;/SPAN&gt;ex &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Exception
            MsgBox(ex.ToString())
        &lt;SPAN style="COLOR: blue"&gt;End Try

    End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;All we need to do here is call SaveChanges on the client proxy. If we haven't made any changes this will do nothing. But if we have then it will send all the changes to the data service in sequence. Depending on the data sets you are working with you may opt for a different strategy like sending the updates to the server immediately after each edit. This is chattier on the wire but reduces the possibility of someone else editing the data and running into database concurrency issues. As I mentioned you can also batch all the requests into a single chunky call to the data service by specifying this in the SaveChanges:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.DataServiceClient.SaveChanges(System.Data.Services.Client.SaveChangesOptions.Batch)&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;&lt;STRONG&gt;Deleting Products&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;To delete a product we can call DeleteObject on the proxy.&amp;nbsp;Finally I remove the object itself from the Products List in which the form is bound through the CollectionView.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;    Private Sub &lt;/SPAN&gt;btnDelete_Click() &lt;SPAN style="COLOR: blue"&gt;Handles &lt;/SPAN&gt;btnDelete.Click
        &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;MessageBox.Show(&lt;SPAN style="COLOR: #a31515"&gt;"Are you sure you want to delete this item?"&lt;/SPAN&gt;, _
                           &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.Title, MessageBoxButton.YesNo) = MessageBoxResult.Yes &lt;SPAN style="COLOR: blue"&gt;Then

            Dim &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Product = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.ProductView.CurrentItem(), Product)
            &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;IsNot Nothing Then
                With Me&lt;/SPAN&gt;.DataServiceClient
                    
                    .DeleteObject(p)
                &lt;SPAN style="COLOR: blue"&gt;End With

                Me&lt;/SPAN&gt;.ProductView.Remove(p)
            &lt;SPAN style="COLOR: blue"&gt;End If
        End If
    End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;STRONG&gt;Editing Products&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Last but not least we need to write the code to edit products in the list. Here we need to check if the category was changed and if so we need to delete the old link to the Category and add the new one.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;btnEdit_Click() &lt;SPAN style="COLOR: blue"&gt;Handles &lt;/SPAN&gt;btnEdit.Click

    &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Product = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.ProductView.CurrentItem(), Product)
    &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;IsNot Nothing Then
      &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;frm &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;ProductDetail()
        frm.Product = p
        frm.CategoryList = &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.CategoryLookup
        &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;oldCategory = p.Category

        &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;frm.ShowDialog() &lt;SPAN style="COLOR: blue"&gt;Then
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;newCategory = p.Category
&lt;SPAN style="COLOR: green"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;SPAN style="COLOR: green"&gt;'If the category was changed, set the new link
            ' then set the product state to updated
        &lt;/SPAN&gt;    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;With Me&lt;/SPAN&gt;.DataServiceClient
                &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;(newCategory &lt;SPAN style="COLOR: blue"&gt;IsNot &lt;/SPAN&gt;oldCategory) &lt;SPAN style="COLOR: blue"&gt;Then&lt;BR&gt;&lt;/SPAN&gt;                    .SetLink(p, &lt;SPAN style="COLOR: #a31515"&gt;"Category"&lt;/SPAN&gt;, newCategory)
                &lt;SPAN style="COLOR: blue"&gt;End If
                &lt;/SPAN&gt;.UpdateObject(p)
            &lt;SPAN style="COLOR: blue"&gt;End With
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;
            'Refresh the grid to pick up change to category 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.DataContext = &lt;SPAN style="COLOR: blue"&gt;Nothing
            Me&lt;/SPAN&gt;.DataContext = &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.Products
        &lt;SPAN style="COLOR: blue"&gt;End If
    End If
End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;When we run the form and make some changes, they all are submitted to the data service. If we didn't specify the Batch option in SaveChanges then the requests are sent in sequence to the data service. Here I've selected an update, HTTP MERGE, operation:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF6_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF6_2.jpg"&gt;&lt;IMG style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=491 alt=AstoriaWPF6 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF6_thumb.jpg" width=730 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/ADO.NETDataServicesBuildingaWPFClient_BAF5/AstoriaWPF6_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;If we did set the Batch option in the save changes you would see only one large payload in Fiddler. I've uploaded the &lt;A href="http://code.msdn.microsoft.com/astoriawpf/" target=_blank mce_href="http://code.msdn.microsoft.com/astoriawpf/"&gt;sample application onto Code Gallery&lt;/A&gt; so have a look. &lt;/P&gt;
&lt;P&gt;In the next post I'll show how we can intercept queries and change operations in order to do some additional processing as well as showing how to add simple validations.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;UPDATE Jan 20-2009: I actually updated the code snippets above and updated the code sample because I uncovered some issues with deletes and enforcing FK associations. &lt;A class="" href="http://blogs.msdn.com/bethmassi/archive/2009/01/20/ado-net-data-services-enforcing-fk-associations-and-a-fix-for-deleting-entities.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/01/20/ado-net-data-services-enforcing-fk-associations-and-a-fix-for-deleting-entities.aspx"&gt;Check that post out here&lt;/A&gt;.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9324201" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Visual+Basic/default.aspx">Visual Basic</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Data/default.aspx">Data</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/N-tier/default.aspx">N-tier</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>Using ADO.NET Data Services</title><link>http://blogs.msdn.com/bethmassi/archive/2009/01/09/using-ado-net-data-services.aspx</link><pubDate>Sat, 10 Jan 2009 06:52:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9303378</guid><dc:creator>Beth Massi</dc:creator><slash:comments>32</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9303378.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9303378</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9303378</wfw:comment><description>&lt;p&gt;This week I worked through a good article on getting started with ADO.NET Data Services (a.k.a Astoria) called &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target="_blank"&gt;Using ADO.NET Data Services&lt;/a&gt;&lt;/em&gt;. If you're not familiar with the technology it's basically a framework for exposing your data models via RESTful web services. So if you are building a remote CRUD data access layer then this is a technology that you'll probably want to look into. It should save you some time especially if you're trying to expose your data over REST. &lt;/p&gt;  &lt;p&gt;(Note: We're in the process of adding Visual Basic code snippets to the article but you can also download &lt;a href="http://code.msdn.microsoft.com/usingastoria" target="_blank"&gt;the VB sample projects here on Code Gallery&lt;/a&gt;.)&lt;/p&gt;  &lt;p&gt;I'm building a few different Windows clients (WPF and Office) to see how we could use ADO.NET Data Services in our n-tier business applications and I'll blog about that soon. But for this post I'd like to highlight the getting started parts &lt;a href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target="_blank"&gt;of the article&lt;/a&gt; that I found most helpful when trying to understand how to work with our database over the web. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;File &amp;gt; New Project &amp;gt; ASP.NET Web Application....&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Creating an ADO.NET Data Service is easy if you are using Visual Studio 2008 SP1. First create a new ASP.NET Web Application:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep1_2.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="456" alt="astoriaStep1" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep1_thumb.jpg" width="640" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This will create a new ASP.NET project with a default.aspx page. If you're just building the service then you can delete this file right away. Next you need to add a new item to the project and select ADO.NET Data Service. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep2_2.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="383" alt="astoriaStep2" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep2_thumb.jpg" width="640" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;For this example I want to expose data in the Northwind sample database so I'm naming the service Northwind.svc. This will add the System.Data.Services and System.Data.Services.Client (the server and client pieces of the framework) to your project. Right-click on the Northwind.svc in the solution explorer and select Set as Start Page. &lt;/p&gt;  &lt;p&gt;This process spits out a code template that sets up your data service by creating a class called Northwind that inherits from DataService. &lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Data.Services
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Linq
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.ServiceModel.Web

&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Northwind
    &lt;span style="color: green"&gt;' TODO: replace [[class name]] with your data class name
    &lt;/span&gt;&lt;span style="color: blue"&gt;Inherits &lt;/span&gt;DataService(&lt;span style="color: blue"&gt;Of &lt;/span&gt;&lt;strong&gt;[[class name]]&lt;/strong&gt;)

    &lt;span style="color: green"&gt;' This method is called only once to initialize service-wide policies.
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Shared Sub &lt;/span&gt;InitializeService(...&lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;End Class&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Notice however that you have some work to do. The DataService acts upon a data model, more specifically, a data model that exposes IQueryable properties. (Take a look at the &lt;a href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=usingastoria&amp;amp;DownloadId=4409" target="_blank"&gt;CustomDataService example&lt;/a&gt; that is explained &lt;a href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target="_blank"&gt;in the MSDN article&lt;/a&gt; if you're interested in creating a compatible data source yourself.) If you're lazy like me then you can use an Entity Framework data model which implements IQueryable by default. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding an Entity Data Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So in order to fill out the [[class name]] of our IQueryable data source we need to create one first. Add a new item to the project and select ADO.NET Entity Data Model. I named the model NorthwindModel.&lt;/p&gt;

&lt;p&gt;\&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep3_2.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="382" alt="astoriaStep3" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep3_thumb.jpg" width="640" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now you can run through the wizard to create the model. I'll just generate it from the database, select all the tables and then hit Finish. This process creates an IQueryable data source called NorthwindEntities. Now we can go back into the data service and fill out the [[class name]]. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Northwind
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;DataService(&lt;span style="color: blue"&gt;Of &lt;/span&gt;&lt;strong&gt;NorthwindEntities&lt;/strong&gt;)&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Setting Access to Tables in the Data Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We also want to control access to the tables in our data model. It's probably a really bad idea to allow read/write access to every table in our database but it's possible by configuring an EntitySetAccessRule on the DataServiceConfiguration that is passed into the InitializeService method. Note that this is a Shared method so it will only run &lt;strong&gt;once &lt;/strong&gt;no matter how many instances of the Northwind DataService are created. You may need to keep that in mind when debugging via Visual Studio and force some rebuilds if you change the code in there.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Northwind
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;DataService(&lt;span style="color: blue"&gt;Of &lt;/span&gt;NorthwindEntities)

    &lt;span style="color: green"&gt;' This method is called only once to initialize service-wide policies.
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Shared Sub &lt;/span&gt;InitializeService(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;config &lt;span style="color: blue"&gt;As &lt;/span&gt;IDataServiceConfiguration)
        &lt;span style="color: green"&gt;' Everyone can party on my data!
        &lt;/span&gt;config.SetEntitySetAccessRule(&lt;span style="color: #a31515"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;, EntitySetRights.All)
    &lt;span style="color: blue"&gt;End Sub

End Class&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;This allows anyone access to update, insert, delete and query the tables in the model. Probably a bad idea. So you can allow just read-only:&lt;/p&gt;

&lt;pre class="code"&gt;config.SetEntitySetAccessRule(&lt;span style="color: #a31515"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;, EntitySetRights.AllRead)&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;You can also write additional web methods for querying and updating the data with some additional processing. I'll get to that in a follow-up post or you can jump into that section &lt;a href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target="_blank"&gt;of the article&lt;/a&gt;. First let's see how we query our data via an HTTP GET in IE.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Querying the Data via HTTP GET&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hitting F5 on the project will now automatically start the service and open the browser to the Northwind.svc which lists all the entities in which we're allowing access in our data model.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep4_2.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="480" alt="astoriaStep4" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep4_thumb.jpg" width="416" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;When we want to query our data, say all the customers, then we can do that via an HTTP GET by typing in the browser address bar: http://localhost:1234/Northwind.svc&lt;strong&gt;/Customers&lt;/strong&gt; and a feed of all the customers in Northwind will be returned. If you're browsing using IE then it will attempt to put a style sheet on the feed, just right-click and view source to see the actual data returned (I'm just displaying the first two in the feed for clarity):&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #a31515"&gt;xml &lt;/span&gt;&lt;span style="color: red"&gt;version&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;1.0&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;encoding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;utf-8&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;standalone&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;yes&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;?&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;feed &lt;/span&gt;&lt;span style="color: red"&gt;xml:base&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://localhost:1308/Northwind.svc/&lt;/span&gt;&amp;quot; 
      &lt;span style="color: red"&gt;xmlns:d&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices&lt;/span&gt;&amp;quot; 
      &lt;span style="color: red"&gt;xmlns:m&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&lt;/span&gt;&amp;quot; 
      &lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://www.w3.org/2005/Atom&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;title &lt;/span&gt;&lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;text&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Customers&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;http://localhost:1308/Northwind.svc/Customers&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;updated&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;2009-01-10T02:17:37Z&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;updated&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;link &lt;/span&gt;&lt;span style="color: red"&gt;rel&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;self&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;entry&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;http://localhost:1308/Northwind.svc/Customers('ALFKI')&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;title &lt;/span&gt;&lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;text&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;updated&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;2009-01-10T02:17:37Z&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;updated&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;author&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;name &lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;author&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;link &lt;/span&gt;&lt;span style="color: red"&gt;rel&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;edit&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers('ALFKI')&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;link &lt;/span&gt;&lt;span style="color: red"&gt;rel&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/related/Orders&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;application/atom+xml;type=feed&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Orders&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers('ALFKI')/Orders&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;link &lt;/span&gt;&lt;span style="color: red"&gt;rel&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/related/CustomerDemographics&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;application/atom+xml;type=feed&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;CustomerDemographics&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers('ALFKI')/CustomerDemographics&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;category &lt;/span&gt;&lt;span style="color: red"&gt;term&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;NorthwindModel.Customers&lt;/span&gt;&amp;quot; 
              &lt;span style="color: red"&gt;scheme&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/scheme&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;content &lt;/span&gt;&lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;application/xml&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;m:properties&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:CustomerID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;ALFKI&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:CustomerID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:CompanyName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Alfreds Futterkiste&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:CompanyName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:ContactName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Maria Anders&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:ContactName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:ContactTitle&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Sales Representative&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:ContactTitle&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Address&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Obere Str. 57&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Address&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:City&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Berlin&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:City&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Region &lt;/span&gt;&lt;span style="color: red"&gt;m:null&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:PostalCode&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;12209&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:PostalCode&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Country&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Germany&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Country&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Phone&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;030-0074321&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Phone&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Fax&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;030-0076545&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Fax&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;m:properties&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;content&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;entry&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;entry&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;http://localhost:1308/Northwind.svc/Customers('ANATR')&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;title &lt;/span&gt;&lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;text&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;updated&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;2009-01-10T02:17:37Z&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;updated&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;author&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;name &lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;author&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;link &lt;/span&gt;&lt;span style="color: red"&gt;rel&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;edit&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers('ANATR')&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;link &lt;/span&gt;&lt;span style="color: red"&gt;rel&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/related/Orders&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;application/atom+xml;type=feed&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Orders&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers('ANATR')/Orders&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;link &lt;/span&gt;&lt;span style="color: red"&gt;rel&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/related/CustomerDemographics&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;application/atom+xml;type=feed&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;CustomerDemographics&lt;/span&gt;&amp;quot; 
          &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Customers('ANATR')/CustomerDemographics&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;category &lt;/span&gt;&lt;span style="color: red"&gt;term&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;NorthwindModel.Customers&lt;/span&gt;&amp;quot; 
              &lt;span style="color: red"&gt;scheme&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/scheme&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;content &lt;/span&gt;&lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;application/xml&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;m:properties&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:CustomerID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;ANATR&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:CustomerID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:CompanyName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Ana Trujillo Emparedados y helados&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:CompanyName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:ContactName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Ana Trujillo&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:ContactName&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:ContactTitle&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Owner&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:ContactTitle&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Address&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Avda. de la Constituci&amp;#243;n 2222&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Address&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:City&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;M&amp;#233;xico D.F.&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:City&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Region &lt;/span&gt;&lt;span style="color: red"&gt;m:null&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:PostalCode&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;05021&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:PostalCode&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Country&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Mexico&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Country&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Phone&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;(5) 555-4729&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Phone&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Fax&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;(5) 555-3745&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;d:Fax&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
      &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;m:properties&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;content&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;entry&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Notice that this also returns the relationship information from the customer to the other tables in the model. So if we wanted to return all the orders for customer ALFKI then we would use the relative URL in this feed like so: &lt;/p&gt;

&lt;p&gt;http://localhost:1234/Northwind.svc/&lt;strong&gt;Customers('ALFKI')/Orders&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BTW, if you're going to get serious about developing RESTful web services I'd highly suggest you &lt;a href="http://www.fiddler2.com/Fiddler2/version.asp" target="_blank"&gt;download Fiddler&lt;/a&gt; which will allow you to inspect your HTTP traffic and payloads. It's a lot easier to view this data in Fiddler than in IE.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building a Simple Client&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This stuff is all fun and games until we want to write a real client against our service. I don't think anyone would be too happy with IE as their client against this service, no matter how cool we wrote it. So let's take a look at a simple client that queries a product, makes a change, and submits it back to the service. This is an example that is illustrated &lt;a href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target="_blank"&gt;in the article&lt;/a&gt; that helped me understand how to make changes to the data. &lt;/p&gt;

&lt;p&gt;First thing we need to do is configure our service so we can query and update the product table. I'm also going to open up the Categories table for read access:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Public Class &lt;/span&gt;Northwind
    &lt;span style="color: blue"&gt;Inherits &lt;/span&gt;DataService(&lt;span style="color: blue"&gt;Of &lt;/span&gt;NorthwindEntities)

    &lt;span style="color: green"&gt;' This method is called only once to initialize service-wide policies.
    &lt;/span&gt;&lt;span style="color: blue"&gt;Public Shared Sub &lt;/span&gt;InitializeService(&lt;span style="color: blue"&gt;ByVal &lt;/span&gt;config &lt;span style="color: blue"&gt;As &lt;/span&gt;IDataServiceConfiguration)
        config.SetEntitySetAccessRule(&lt;span style="color: #a31515"&gt;&amp;quot;&lt;strong&gt;Products&lt;/strong&gt;&amp;quot;&lt;/span&gt;, EntitySetRights.All)
        config.SetEntitySetAccessRule(&lt;span style="color: #a31515"&gt;&amp;quot;&lt;strong&gt;Categories&lt;/strong&gt;&amp;quot;&lt;/span&gt;, EntitySetRights.AllRead)
    &lt;span style="color: blue"&gt;End Sub

End Class&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Now let's add a simple console application (real clients soon, I promise!) to illustrate the client-side code it takes to query and update a product in our database. Once you add a new console application to the solution we need to add the service reference to our Northwind Data Service. Right click on the client console application and select &amp;quot;Add Service Reference&amp;quot;. When the dialog opens click the Discover button and it should find the data service. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep5_2.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="480" alt="astoriaStep5" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/UsingADO.NETDataServices_EBA6/astoriaStep5_thumb.jpg" width="597" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Once we add this service reference to our client this will automatically generate the client-side proxy that inherits from DataServiceContext and the necessary entities to work with our data service. It also adds a reference to the System.Data.Services.Client assembly which has the client-side framework where the DataServiceContext object lives. This is another added benefit than you creating a remote data access layer yourself. You tell the DataServiceContext how to track changes to the entities and it can can batch up requests and send them at once to the service. &lt;/p&gt;

&lt;p&gt;One of cool things about having an IQueryable data source exposed through a data service is that you can use LINQ over the entities generated on the client-side and the framework will handle translating that to HTTP requests. You can dive deeper &lt;a href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target="_blank"&gt;into the article&lt;/a&gt; on the exact query syntax it can support but it's pretty full featured.&amp;#160; For instance back on the IE client, if we just want to return the top 2 customers we could type: http://localhost:1234/Northwind.svc/&lt;strong&gt;Customers?$top=2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But when we're working with a managed client we can write a LINQ query against the data service instead. Here I'm returning all the products in the Beverages category:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;MyDataServiceClient.ServiceReference1

&lt;span style="color: blue"&gt;Module &lt;/span&gt;Module1
    &lt;span style="color: blue"&gt;Private &lt;/span&gt;ServiceURI &lt;span style="color: blue"&gt;As &lt;/span&gt;Uri = &lt;span style="color: blue"&gt;New &lt;/span&gt;Uri(&lt;span style="color: #a31515"&gt;&amp;quot;http://localhost:1308/Northwind.svc/&amp;quot;&lt;/span&gt;)

    &lt;span style="color: blue"&gt;Sub &lt;/span&gt;Main()
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;ctx &lt;span style="color: blue"&gt;As New &lt;/span&gt;NorthwindEntities(ServiceURI)

        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;results = &lt;span style="color: blue"&gt;From &lt;/span&gt;p &lt;span style="color: blue"&gt;In &lt;/span&gt;ctx.Products _
                      &lt;span style="color: blue"&gt;Where &lt;/span&gt;p.Categories.CategoryName = &lt;span style="color: #a31515"&gt;&amp;quot;Beverages&amp;quot; &lt;/span&gt;

        &lt;span style="color: blue"&gt;For Each &lt;/span&gt;p &lt;span style="color: blue"&gt;In &lt;/span&gt;results
            Console.WriteLine(p.ProductName)
        &lt;span style="color: blue"&gt;Next
        &lt;/span&gt;Console.ReadLine()
    &lt;span style="color: blue"&gt;End Sub

End Module&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Pretty slick. Notice that since I'm using the Categories in the query, I have to enable access to that on the service side otherwise I'll get an error when running the client. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saving Changes through the ADO.NET Data Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to update the database we tell the DataServiceContext that we updated the object and then tell it to pass the change to the server by calling SaveChanges.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;MyDataServiceClient.ServiceReference1

&lt;span style="color: blue"&gt;Module &lt;/span&gt;Module1
    &lt;span style="color: blue"&gt;Private &lt;/span&gt;ServiceURI &lt;span style="color: blue"&gt;As &lt;/span&gt;Uri = &lt;span style="color: blue"&gt;New &lt;/span&gt;Uri(&lt;span style="color: #a31515"&gt;&amp;quot;http://localhost:1308/Northwind.svc/&amp;quot;&lt;/span&gt;)

    &lt;span style="color: blue"&gt;Sub &lt;/span&gt;Main()
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;ctx &lt;span style="color: blue"&gt;As New &lt;/span&gt;NorthwindEntities(ServiceURI)

        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;product = (&lt;span style="color: blue"&gt;From &lt;/span&gt;p &lt;span style="color: blue"&gt;In &lt;/span&gt;ctx.Products _
                      &lt;span style="color: blue"&gt;Where &lt;/span&gt;p.ProductName = &lt;span style="color: #a31515"&gt;&amp;quot;Chai&amp;quot;&lt;/span&gt;).FirstOrDefault()

        &lt;span style="color: blue"&gt;If &lt;/span&gt;product &lt;span style="color: blue"&gt;IsNot Nothing Then

            &lt;/span&gt;product.ProductName = &lt;span style="color: #a31515"&gt;&amp;quot;Chai Tea&amp;quot;
            &lt;/span&gt;ctx.UpdateObject(product)

            &lt;span style="color: blue"&gt;Try
                &lt;/span&gt;&lt;span style="color: green"&gt;'You can batch up changes on the DataServiceContext
                ' before calling SaveChanges. This will hit the service.
                &lt;/span&gt;ctx.SaveChanges()
                Console.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Saved Product&amp;quot;&lt;/span&gt;)
            &lt;span style="color: blue"&gt;Catch &lt;/span&gt;ex &lt;span style="color: blue"&gt;As &lt;/span&gt;Exception
                Console.WriteLine(ex.ToString())
            &lt;span style="color: blue"&gt;End Try
        End If
    End Sub

End Module&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Nice. In the next post I'll dig a little deeper into how we can intercept queries so that we can do some server-side processing first as well as how we can add additional processing methods to our service in order to perform custom querying and validation. I'm also building a WPF client for doing batch editing that I'll introduce. For now, please read the &lt;a href="http://msdn.microsoft.com/en-us/library/cc907912.aspx" target="_blank"&gt;article on MSDN for more information&lt;/a&gt;. Until next time....&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9303378" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Visual+Basic/default.aspx">Visual Basic</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Article/default.aspx">Article</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Data/default.aspx">Data</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Entity+Framework/default.aspx">Entity Framework</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>More PDC Tidbits, Data Everywhere, Visual Studio 2010 CTP</title><link>http://blogs.msdn.com/bethmassi/archive/2008/10/29/more-pdc-tidbits-data-everywhere-visual-studio-2010-ctp.aspx</link><pubDate>Thu, 30 Oct 2008 02:07:57 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9023208</guid><dc:creator>Beth Massi</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9023208.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9023208</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9023208</wfw:comment><description>&lt;p&gt;Day 3 at PDC is off to a great start so far. I just attended a session on the architecture and development of the content delivery infrastructure and Silverlight client for the &lt;a href="http://www.nbcolympics.com/" target="_blank"&gt;NBC Olympics online&lt;/a&gt;. It's pretty amazing how they pulled it off but one of the reasons for the success was &lt;a href="http://en.wikipedia.org/wiki/Scrum_(development)" target="_blank"&gt;scrumming&lt;/a&gt; and face-to-face meetings. With teams scattered all over the globe from Redmond to Beijing it takes great project management besides super technical skills to drive success. This is key to any software project, not just large ones like this.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;DATA EVERYWHERE&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Now I'm sitting in a session with Pablo Castro, a Software Architect over in SQL, on offline-enabled data services and desktop applications. This one is really good. I'm really interested in this one because on my former system that I developed we implemented our own data caching mechanisms and some of the challenges once you decide what data can be offline is how to efficiently synchronize it with the server as well as determining how stale you can tolerate the data. The plumbing for serializing and syncing the data is non-trivial so I'm happy to see these frameworks that handle that for you. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/FunStuffPDC_D5DA/IMG_1136_1.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; margin: 0px 10px 0px 0px; border-left: 0px; border-bottom: 0px" height="325" alt="IMG_1136" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/FunStuffPDC_D5DA/IMG_1136_thumb_1.jpg" width="412" align="left" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/data/bb931106.aspx" target="_blank"&gt;ADO.NET Data Services (Astoria)&lt;/a&gt; make it really really easy for you to put your data on the web. I've been getting into it since it was added to Visual Studio 2008 SP1. I think that combining this with &lt;a href="http://msdn.microsoft.com/en-us/sync/default.aspx" target="_blank"&gt;Sync Services&lt;/a&gt; will make a great framework for you to build an easy data caching framework as well as enable you to &amp;quot;play back&amp;quot; calls to the service for you once you get back online. Pablo referred to this as &amp;quot;Astoria Offline&amp;quot; integrated into Visual Studio. I can't wait. &lt;/p&gt;  &lt;p&gt;He built a simple ADO.NET Data Service (&lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/10/21/channel-9-interview-ado-net-data-services-in-visual-studio-2008-sp1.aspx" target="_blank"&gt;just like Saaid showed here&lt;/a&gt;) using the Entity Framework to model some data. The service then exposes this model to the web. The new thing he showed is that when creating the service there was an option on the dialog to create an offline enabled service. This adds code to enable sync services and scripts to modify the SQL Server database schema to enable change tracking on the tables (similar to how you do it now in VS 2008 using sync services, &lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/08/08/channel-9-interview-sql-2008-occasionally-connected-client-support-in-visual-studio-sp1.aspx" target="_blank"&gt;like Milind showed here&lt;/a&gt;). Then Pablo added a WPF client. and added a Service Reference to the data service. Because it was set up as an offline-enabled service it asks you if you want to take the service offline. If you say yes then it downloads the metadata from the service, creates a local SQL CE database and then adds an Entity Framework model to the local database. This allows you to code against the local data model which then syncs with the service behind the scenes using an orchestrator. VERY COOL. Its amazing what you can do with Visual Studio.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;DOWNLOADS&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Speaking of Visual Studio --- &lt;a href="http://go.microsoft.com/fwlink/?LinkId=131310" target="_blank"&gt;Visual Studio 2010 and .NET 4.0 CTP&lt;/a&gt; was released on Monday so have a look at an early build of the next version of VS. I'll be bugging the Visual Studio teams for Channel 9 videos in the coming months to show us what they got in there and how to use it. Now's the time for feedback so play with it and tell us about it on the &lt;a href="http://go.microsoft.com/fwlink/?LinkId=129231"&gt;Dev10 CTP Feedback page&lt;/a&gt; and the &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/category/vs2010ctp"&gt;feedback forums&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Other things to look at and play with:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkID=128752"&gt;Windows Azure Tools for Microsoft Visual Studio CTP&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://channel9.msdn.com/tags/pdcnews.announcements//" target="_blank"&gt;Channel 9 PDC news and announcements&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://microsoftpdc.com/" target="_blank"&gt;PDC Online&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9023208" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Community/default.aspx">Community</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/DevCenter/default.aspx">DevCenter</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item></channel></rss>