<?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 : Article, LINQ</title><link>http://blogs.msdn.com/bethmassi/archive/tags/Article/LINQ/default.aspx</link><description>Tags: Article, LINQ</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Merging Text &amp; Photos into a Word Document using Open XML SDK</title><link>http://blogs.msdn.com/bethmassi/archive/2009/09/24/merging-text-photos-into-a-word-document-using-open-xml-sdk.aspx</link><pubDate>Fri, 25 Sep 2009 00:55:10 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9899172</guid><dc:creator>Beth Massi</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9899172.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9899172</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9899172</wfw:comment><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/09/23/mail-merging-into-a-single-word-document-using-xml-literals.aspx" target="_blank"&gt;Yesterday I posted&lt;/a&gt; about how we could create a letter generator (mail merge) that took data from a database to create a Word 2007 document using the System.IO.Packaging class. I showed how to take data from Northwind using a single LINQ query to create XDocument objects representing letters to customers and then create a single document of all the data using XML Literals. &lt;/p&gt; &lt;p&gt;Today I want to show how we can embed images into the documents as well as text. Since we’re using Northwind for this example, we’ll use the Employee.Photo field from that database. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;The Letter Template with Photo&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The first thing to do is create a letter template with our field placeholders as well as an image placeholder. We’ll also need to insert a page break at the end because we’re going to merge all the letters into a single document for easy printing:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MergingTextPhotosintoaSingleWordDocument_E6F4/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/MergingTextPhotosintoaSingleWordDocument_E6F4/image_thumb.png" width="668" height="555"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The next step is to grab the document.xml from this docx file. Because it’s an Open XML package, as I showed in &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/09/23/mail-merging-into-a-single-word-document-using-xml-literals.aspx" target="_blank"&gt;yesterday’s post&lt;/a&gt;, we can just rename this file with a .zip extension temporarily and drill into the word\document.xml. However, there’s an easier way to work with these packages by installing the &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;Open XML package editor&lt;/a&gt; Visual Studio add-in from 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 download&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MergingTextPhotosintoaSingleWordDocument_E6F4/image_8.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; margin: 0px 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/MergingTextPhotosintoaSingleWordDocument_E6F4/image_thumb_3.png" width="457" height="327"&gt;&lt;/a&gt;Once you install 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;, save this template in your project. Then you can just double-click on the .docx file in the Solution Explorer and it will open the package editor (it also works with .pptx and .xslx files). Now you can drill into the document.xml directly in Visual Studio and inspect all the parts of the package easily. &lt;/p&gt; &lt;p&gt;The difference between this template and the template we used yesterday is there is an image imbedded into the document. So you will see an image embedded into the package in the media folder. This is referred to as an “image part”. This part is linked to the “main document part” which is the word\document.xml file. The Open XML package editor shows the links (relationships) to all the parts. When you look at the relationship properties you’ll see that it has a unique ID. This is the same ID that you will see in the main document part at the point where we embedded the image, in our case it’s set to &lt;strong&gt;rId4&lt;/strong&gt;. (I’ve omitted all the WordProccessingML 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;"&lt;span style="color: blue"&gt;1.0&lt;/span&gt;" &lt;span style="color: red"&gt;encoding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;utf-8&lt;/span&gt;" &lt;span style="color: red"&gt;standalone&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;yes&lt;/span&gt;"&lt;span style="color: blue"&gt;?&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:document ...&lt;br&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:body&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt; ...&lt;/span&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:drawing&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt; ...&lt;br&gt;&lt;/pre&gt;&lt;/span&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;              &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:graphic &lt;/span&gt;&lt;span style="color: red"&gt;xmlns:a&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;http://schemas.openxmlformats.org/drawingml/2006/main&lt;/span&gt;"&lt;span style="color: blue"&gt;&amp;gt;
              &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:graphicData &lt;/span&gt;&lt;span style="color: red"&gt;uri&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;http://schemas.openxmlformats.org/drawingml/2006/picture&lt;/span&gt;"&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:pic &lt;/span&gt;&lt;span style="color: red"&gt;xmlns:pic&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;http://schemas.openxmlformats.org/drawingml/2006/picture&lt;/span&gt;"&lt;span style="color: blue"&gt;&amp;gt;
                  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:nvPicPr&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:cNvPr &lt;/span&gt;&lt;span style="color: red"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;=&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;=&lt;/span&gt;"&lt;span style="color: blue"&gt;image1.png&lt;/span&gt;"&lt;span style="color: blue"&gt;/&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:cNvPicPr&lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
                  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:nvPicPr&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:blipFill&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:blip &lt;/span&gt;&lt;strong&gt;&lt;span style="color: red"&gt;r:embed&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;rId4&lt;/span&gt;"&lt;/strong&gt; &lt;span style="color: red"&gt;cstate&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;print&lt;/span&gt;"&lt;span style="color: blue"&gt;/&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:stretch&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:fillRect&lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:stretch&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:blipFill&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:spPr&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:xfrm&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:off &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: blue"&gt;0&lt;/span&gt;" &lt;span style="color: red"&gt;y&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;0&lt;/span&gt;"&lt;span style="color: blue"&gt;/&amp;gt;
                      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:ext &lt;/span&gt;&lt;span style="color: red"&gt;cx&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;1829055&lt;/span&gt;" &lt;span style="color: red"&gt;cy&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;2124372&lt;/span&gt;"&lt;span style="color: blue"&gt;/&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:xfrm&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:prstGeom &lt;/span&gt;&lt;span style="color: red"&gt;prst&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;rect&lt;/span&gt;"&lt;span style="color: blue"&gt;&amp;gt;
                      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:avLst&lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:prstGeom&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:spPr&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;pic:pic&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
              &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:graphicData&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a:graphic&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt; ...
          &lt;/span&gt;&lt;span style="color: blue"&gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:drawing&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt; ...&lt;br&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:p &lt;/span&gt;&lt;span style="color: red"&gt;w:rsidR&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;00622A50&lt;/span&gt;" &lt;span style="color: red"&gt;w:rsidRDefault&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;00622A50&lt;/span&gt;"&lt;span style="color: blue"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:r&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:br &lt;/span&gt;&lt;span style="color: red"&gt;w:type&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;"&lt;span style="color: blue"&gt;page&lt;/span&gt;"&lt;span style="color: blue"&gt;/&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:r&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt; ...&lt;/span&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:body&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;w:document&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;&lt;strong&gt;Installing the Open XML SDK&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As I mentioned yesterday, manipulating the package directly with the System.IO.Packaging classes gets a little bit tricky when you have to start adding embedded images and objects and linking them together. Instead, it’s easier to use the Open XML SDK to do this because it will handle linking new image parts we add to the package automatically for us. The SDK provides a strongly-typed way of accessing the parts in a package so it cuts down on the amount of code you have to write yourself.&amp;nbsp; Version 1.0 requires only .NET 2.0, Version 2 requires .NET 3.5 and uses LINQ to provide more functionality when querying the parts. This version is currently a CTP. For what we’re doing you can use either version but I have Version 2 installed. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=AD0B72FB-4A1D-4C52-BDB5-7DD7E816D046&amp;amp;displaylang=en" target="_blank"&gt;Download Open XML Format SDK 1.0&lt;/a&gt; 
&lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c6e744e5-36e9-45f5-8d8c-331df206e0d0&amp;amp;DisplayLang=en" target="_blank"&gt;Download Open XML Format SDK 2.0&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The assembly that is installed in the GAC when you install the SDK is called DocumentFormat.OpenXml.dll and you’ll need to add a project reference to this. When you distribute your application you can simply xcopy the assembly with your application for easy deployment. (After you add the reference, select it in the Server Explorer and then in the Properties window set Copy Local to True in order to have it outputted to the \bin folder when you build your application.)&lt;/p&gt;
&lt;p&gt;Now we can add the namespace imports we’ll be working with at the top of our program, including the DocumentFormat.OpenXml.Packaging namespace:&lt;/p&gt;&lt;pre class="code"&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:w&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;http://schemas.openxmlformats.org/wordprocessingml/2006/main&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
&lt;/span&gt;&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.Xml
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;System.IO
&lt;span style="color: blue"&gt;Imports &lt;/span&gt;DocumentFormat.OpenXml.Packaging&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;&lt;strong&gt;Modifying the Letter Class and LINQ Query to Get the Photo&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In order to create letters for our customers in the database, we want to end up with a collection of XDocuments with our data merged into them. I created a Letter class that has two properties, CustomerID As String and Document As XDocument. We’re also going to add a new property for the photo byte array called EmployeePhoto As Byte() and OrderID as Integer. Next we need to modify the query so that it selects the photo as well as add the above WordProcessingML into our XML Literal to specify where the image should appear in the document. Because the relationship IDs must be unique, I’m going to use the OrderID as the suffix for the relationship ID for each of the images we want to embed. Like before, we can use embedded expressions to merge the data into the right places in the XDocument. 
&lt;p&gt;(I’ve omitted all the XML with the embedded expressions for clarity, take a loot at &lt;a href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=openxmlvb&amp;amp;DownloadId=7325"&gt;the code sample&lt;/a&gt; for the whole listing.) The bolded areas show the modified sections of the query:&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;letters = _
&lt;span style="color: blue"&gt;  From &lt;/span&gt;Order &lt;span style="color: blue"&gt;In &lt;/span&gt;db.Orders _
&lt;span style="color: blue"&gt;  Join &lt;/span&gt;Employee &lt;span style="color: blue"&gt;In &lt;/span&gt;db.Employees _
&lt;span style="color: blue"&gt;    On &lt;/span&gt;Order.EmployeeID &lt;span style="color: blue"&gt;Equals &lt;/span&gt;Employee.EmployeeID _
&lt;span style="color: blue"&gt;  Where &lt;/span&gt;Order.OrderDate &lt;span style="color: blue"&gt;IsNot Nothing AndAlso &lt;/span&gt;_
    Order.ShippedDate &lt;span style="color: blue"&gt;IsNot Nothing AndAlso &lt;/span&gt;_
    Order.ShippedDate.Value.Date &amp;gt;= #1/1/1998# _
&lt;span style="color: blue"&gt;  Let &lt;/span&gt;DateOrder = Order.OrderDate.Value.ToShortDateString _
&lt;span style="color: blue"&gt;  Let &lt;/span&gt;DateShip = Order.ShippedDate.Value.ToShortDateString _
&lt;span style="color: blue"&gt;  Select New &lt;/span&gt;Letter &lt;span style="color: blue"&gt;With &lt;/span&gt;{ _
    .CustomerID = Order.CustomerID, _&lt;br&gt;    &lt;strong&gt;.OrderID = Order.OrderID, _
&lt;br&gt;&lt;br&gt;&lt;br&gt;    .EmployeePhoto = &lt;span style="color: blue"&gt;If&lt;/span&gt;(Employee.Photo &lt;span style="color: blue"&gt;IsNot Nothing&lt;/span&gt;, Employee.Photo.ToArray, &lt;span style="color: blue"&gt;Nothing&lt;/span&gt;), _&lt;/strong&gt;
    .Document = &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;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;1.0&lt;/span&gt;&lt;span style="color: #555555"&gt;" &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;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;utf-8&lt;/span&gt;&lt;span style="color: #555555"&gt;" &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;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;yes&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;?&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:document ... &lt;br&gt;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:body&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt; ...
&lt;/span&gt;&lt;span style="color: #6464b9"&gt;                &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:p &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:rsidR&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;00A9498E&lt;/span&gt;&lt;span style="color: #555555"&gt;" &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:rsidRDefault&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;00A9498E&lt;/span&gt;&lt;span style="color: #555555"&gt;" &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:rsidP&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;00AA2EC6&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t &lt;/span&gt;&lt;span style="color: #b96464"&gt;xml:space&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;preserve&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #555555"&gt;If you have any issues please contact &lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:proofErr &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:type&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;spellStart&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;/&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background: #fffebf; color: #555555"&gt;&amp;lt;%=&lt;/span&gt; Employee.FirstName &amp;amp; &lt;span style="color: #a31515"&gt;" " &lt;/span&gt;&amp;amp; Employee.LastName &lt;span style="background: #fffebf; color: #555555"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:proofErr &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:type&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;spellEnd&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;/&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t &lt;/span&gt;&lt;span style="color: #b96464"&gt;xml:space&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;preserve&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: #555555"&gt;at&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:rsidR&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;005F35D6&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t &lt;/span&gt;&lt;span style="color: #b96464"&gt;xml:space&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;preserve&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: #555555"&gt;ext.&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t &lt;/span&gt;&lt;span style="color: #b96464"&gt;xml:space&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;preserve&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:rsidR&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;005F35D6&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background: #fffebf; color: #555555"&gt;&amp;lt;%=&lt;/span&gt; Employee.Extension &lt;span style="background: #fffebf; color: #555555"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:t&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:p&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt; ...
                        &lt;/span&gt;&lt;strong&gt;&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:drawing&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: #6464b9"&gt;&amp;gt; ...
&lt;/span&gt;&lt;span style="color: #6464b9"&gt;                            &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;pic:blipFill&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: #6464b9"&gt;&amp;gt; ...
                                &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;a:blip &lt;/span&gt;&lt;span style="color: #b96464"&gt;r:embed&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="background: #fffebf; color: #555555"&gt;&amp;lt;%=&lt;/span&gt; &lt;/strong&gt;&lt;span style="color: #a31515"&gt;"rId" &lt;/span&gt;&amp;amp; &lt;strong&gt;Order.OrderID &lt;span style="background: #fffebf; color: #555555"&gt;%&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: #6464b9"&gt;/&amp;gt; ...
&lt;/span&gt;&lt;span style="color: #6464b9"&gt;                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:drawing&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: #6464b9"&gt;&amp;gt; ...
&lt;/span&gt;&lt;span style="color: #6464b9"&gt;                        &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:p &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:rsidR&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;00622A50&lt;/span&gt;&lt;span style="color: #555555"&gt;" &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:rsidRDefault&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;00622A50&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                                &amp;lt;&lt;/span&gt;&lt;span style="color: #844646"&gt;w:br &lt;/span&gt;&lt;span style="color: #b96464"&gt;w:type&lt;/span&gt;&lt;span style="color: #6464b9"&gt;=&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;span style="color: #6464b9"&gt;page&lt;/span&gt;&lt;span style="color: #555555"&gt;"&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: #6464b9"&gt;/&amp;gt;
                            &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:r&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:p&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: #6464b9"&gt;&lt;strong&gt;&amp;gt; ...&lt;/strong&gt;
&lt;/span&gt;&lt;span style="color: #6464b9"&gt;                    &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:body&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;
                &amp;lt;/&lt;/span&gt;&lt;span style="color: #844646"&gt;w:document&lt;/span&gt;&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;}&lt;/pre&gt;
&lt;p&gt;The query returns an IEnumerable(Of Letter) objects with the Document property set to the document.xml data for that customer and the EmployeePhoto set to the photo byte array. If we wanted to create separate documents (which is exactly what I demonstrated in my &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/08/17/devproconnections-article-taking-advantage-of-linq-and-xml-in-microsoft-office-2007.aspx" target="_blank"&gt;DevProConnections article&lt;/a&gt;) it’s actually pretty simple because all we need to do is copy the template and then replace the document.xml and the image data, we don’t have to mess with the relationship ID at all. However if we want to create a single document with all our letters we need to delete the placeholder image part and add new unique image parts for the Letter.EmployeePhoto. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adding and Linking the Images into a Single Word Document&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Because relationship IDs must be unique in a document I used the OrderID as the embedded expression for the r:embed attribute in the XML Literal above. You can choose to use any unique ID you want but it must start with an alpha character, that’s why I prefixed it with “rId”. When you use the Open XML SDK to add the new image parts we have to specify the relationship ID to use. To update the code we wrote yesterday to work with the Open XML SDK and also work with images we first need to add a call to open the Word document template, grab the main document part and then delete the image part by calling DeletePart:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: green"&gt;'Place the letters in a separate directory
&lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;sourceFile = CurDir() &amp;amp; &lt;span style="color: #a31515"&gt;"\LetterTemplate.docx"
&lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;letterDir = CurDir() &amp;amp; &lt;span style="color: #a31515"&gt;"\Letters\"
&lt;/span&gt;&lt;span style="color: blue"&gt;My&lt;/span&gt;.Computer.FileSystem.CreateDirectory(letterDir)

&lt;span style="color: blue"&gt;Dim &lt;/span&gt;mergeFile = letterDir &amp;amp; &lt;span style="color: #a31515"&gt;"AllLetters.docx"
&lt;/span&gt;&lt;span style="color: blue"&gt;My&lt;/span&gt;.Computer.FileSystem.CopyFile(sourceFile, mergeFile, &lt;span style="color: blue"&gt;True&lt;/span&gt;)

&lt;span style="color: green"&gt;'Open the Document template using the Open XML SDK
&lt;/span&gt;&lt;span style="color: blue"&gt;Using &lt;/span&gt;wordDoc = WordprocessingDocument.Open(mergeFile, &lt;span style="color: blue"&gt;True&lt;/span&gt;)

&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: green"&gt;'Delete the placeholder image from the template so we can replace it with the real photos
    &lt;/span&gt;mainPart.DeletePart(&lt;span style="color: #a31515"&gt;"rId4"&lt;/span&gt;)&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;This opens the Word document as read/write and then deletes the placeholder image. You should also notice at this point that the code is a bit simpler to open the package than yesterday because we don’t have to declare the relative URI’s or content types. The Open XML SDK helps us here. Next we need to load the document.xml into an XElement object and grab the body:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;    Dim &lt;/span&gt;mainDocumentXML &lt;span style="color: blue"&gt;As &lt;/span&gt;XElement
    &lt;span style="color: blue"&gt;Using &lt;/span&gt;sr &lt;span style="color: blue"&gt;As New &lt;/span&gt;StreamReader(mainPart.GetStream)
        mainDocumentXML = XElement.Load(sr)
    &lt;span style="color: blue"&gt;End Using

    Dim &lt;/span&gt;mainBody = mainDocumentXML...&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;w:body&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.First()
    &lt;span style="color: blue"&gt;Dim &lt;/span&gt;i = 0&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Now we can loop through all the letters, grab the body of those XDocuments and then add an image part. We need to specify the content type and the relationship ID that must match what we embedded in the XML Literal in our query. Then we can either replace the main document body with the first letter (overwrite our placeholder data) otherwise we append the rest of the letter contents into the document:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;    For Each &lt;/span&gt;letter &lt;span style="color: blue"&gt;In &lt;/span&gt;letters
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;nextBody = letter.Document...&lt;span style="color: #6464b9"&gt;&amp;lt;&lt;/span&gt;w:body&lt;span style="color: #6464b9"&gt;&amp;gt;&lt;/span&gt;.First()
        &lt;span&gt;'Add the new imagePart. The SDK takes care of linking this properly.
       &lt;strong&gt; Dim &lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;imagePart = mainPart.AddImagePart(&lt;span style="color: #a31515"&gt;"image/png"&lt;/span&gt;, &lt;span style="color: #a31515"&gt;"rId" &lt;/span&gt;&amp;amp; letter.OrderID)&lt;/strong&gt;

        &lt;span style="color: blue"&gt;If &lt;/span&gt;i = 0 &lt;span style="color: blue"&gt;Then
           &lt;/span&gt;&lt;span style="color: green"&gt;'Replace the first body contents in the template
           &lt;/span&gt;mainBody.ReplaceNodes(nextBody.Elements())
        &lt;span style="color: blue"&gt;Else
           &lt;/span&gt;&lt;span style="color: green"&gt;'Otherwise append the next letter contents
           &lt;/span&gt;mainBody.Add(nextBody.Elements())
        &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;Next we need to feed the byte array data into the ImagePart. Note that since I’m using Northwind for this example there is an OLE header on those images that we must strip off that is 78 bytes. If you are using your own images stored in SQL Server you won’t have to do that:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: green"&gt;        'Now feed the byte array into the ImagePart
        &lt;/span&gt;&lt;span style="color: blue"&gt;If &lt;/span&gt;letter.EmployeePhoto &lt;span style="color: blue"&gt;IsNot Nothing Then
            &lt;/span&gt;&lt;span style="color: green"&gt;'Using ms As New System.IO.MemoryStream(letter.EmployeePhoto.ToArray)
            'NOTE: Northwind Photos have an OLE header on them that we must strip off.
            ' You don't have to do this if you are using your own SQL-server stored images
            &lt;/span&gt;&lt;span style="color: blue"&gt;Using &lt;/span&gt;ms &lt;span style="color: blue"&gt;As New &lt;/span&gt;System.IO.MemoryStream(letter.EmployeePhoto, 78, _
                                                   letter.EmployeePhoto.Length - 78)
                imagePart.FeedData(ms)
            &lt;span style="color: blue"&gt;End Using
        End If

        &lt;/span&gt;i += 1
    &lt;span style="color: blue"&gt;Next&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Now that we’ve built up the document XML, added our image parts and linked them properly, the final step is to replace the document part with our XML just like before:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: green"&gt;    'Replace the document part with our XML
    &lt;/span&gt;&lt;span style="color: blue"&gt;Using &lt;/span&gt;sw &lt;span style="color: blue"&gt;As New &lt;/span&gt;StreamWriter(mainPart.GetStream(FileMode.Create))
        mainDocumentXML.Save(sw)
    &lt;span style="color: blue"&gt;End Using

End Using&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Now when we run the application you will see a single document with all the letters, including photos, that’s much easier to print than multiple files. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MergingTextPhotosintoaSingleWordDocument_E6F4/image_12.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MergingTextPhotosintoaSingleWordDocument_E6F4/image_thumb_5.png" width="687" height="255"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There’s Always Room for Improvement&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;LINQ &amp;amp; Northwind savvy folks may notice that I’m actually creating duplicates of the employee photos. Since I’m flattening out the data in my query to have 1 photo per order there could be an unnecessary amount of duplicate images. This can cause the document to get bloated. To be more efficient we should reuse the relationship ID’s to the images if they are the same on multiple orders. One approach would be to modify the LINQ query and Letter object to select the EmployeePhoto and then have a collection of order &amp;amp; document data under that. I’ll leave that experiment up to you :-)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=openxmlvb&amp;amp;DownloadId=7325" target="_blank"&gt;Take a look at the full code listing for this example&lt;/a&gt; as well as the &lt;a href="http://code.msdn.microsoft.com/openxmlvb" target="_blank"&gt;complete project with other Open XML examples here on Code Gallery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9899172" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bethmassi/archive/tags/LINQ/default.aspx">LINQ</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/VSTO/default.aspx">VSTO</category></item><item><title>Mail Merging Into a Single Word Document Using XML Literals</title><link>http://blogs.msdn.com/bethmassi/archive/2009/09/23/mail-merging-into-a-single-word-document-using-xml-literals.aspx</link><pubDate>Thu, 24 Sep 2009 02:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9898711</guid><dc:creator>Beth Massi</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9898711.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9898711</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9898711</wfw:comment><description>&lt;P&gt;With the release of Microsoft Office 2007 we can work with a much simpler, standard, XML format called &lt;A href="http://www.ecma-international.org/publications/standards/Ecma-376.htm" target=_blank mce_href="http://www.ecma-international.org/publications/standards/Ecma-376.htm"&gt;Open XML&lt;/A&gt; which opens the door for many types of applications that cannot work via COM. What if you needed to build a scalable web service that processes many documents in high volume? What if you wanted to quickly read or write to these formats from a client application but wanted to have minimal dependencies on other applications? These types of programs do not want to require Microsoft Office be installed to run. The cool thing is you have the tools already with Visual Basic 2008. XML Literals are an easy way to manipulate any kind of XML, including Open XML.&lt;/P&gt;
&lt;P&gt;I’ve written before on how to use XML Literals to manipulate Word documents, if you missed them:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/08/17/devproconnections-article-taking-advantage-of-linq-and-xml-in-microsoft-office-2007.aspx" mce_href="http://blogs.msdn.com/bethmassi/archive/2009/08/17/devproconnections-article-taking-advantage-of-linq-and-xml-in-microsoft-office-2007.aspx"&gt;&lt;STRONG&gt;DevProConnections Article: Taking Advantage of LINQ and XML in Microsoft Office 2007&lt;/STRONG&gt;&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;Sample: &lt;A href="http://code.msdn.microsoft.com/openxmlvb" mce_href="http://code.msdn.microsoft.com/openxmlvb"&gt;Working with Open XML in Visual Basic&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" mce_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/2008/07/30/accessing-openxml-document-parts-with-the-openxml-sdk.aspx" mce_href="http://blogs.msdn.com/bethmassi/archive/2008/07/30/accessing-openxml-document-parts-with-the-openxml-sdk.aspx"&gt;Accessing Open XML Document Parts with the Open XML SDK&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx"&gt;Mail Merging with Word, LINQ and XML Literals in VB&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;If you aren’t familiar with XML Literals or Open XML then I’d suggest reading the article &lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/08/17/devproconnections-article-taking-advantage-of-linq-and-xml-in-microsoft-office-2007.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2009/08/17/devproconnections-article-taking-advantage-of-linq-and-xml-in-microsoft-office-2007.aspx"&gt;in the first bullet above&lt;/A&gt; first. It’s a great intro into XML Literals, Open XML and it also demonstrates a couple practical ways of reading and writing to Word document formats directly. &lt;/P&gt;
&lt;P&gt;Recently I got a great question on how to change the program outlined in the &lt;A href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx"&gt;last bullet above&lt;/A&gt; to merge letters we were creating on the fly from a database into a single document instead of multiple documents like we’re doing. This would make it much easier for an end user to print them. That’s such an obvious thing I can’t believe I didn’t think of that! For those of you that aren’t familiar with what we did I’ll give a quick recap of that application. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Creating Word Documents with XML Literals&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;What I wanted to do is take all the Customers in the Northwind database who had some orders shipping today and send them thank you letters. To get started I created a new Word 2007 document with the letter text and some placeholder field names to indicate where I want the data:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MailMergingaSingleWordDocumentUsingXMLLi_C84D/image_6.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MailMergingaSingleWordDocumentUsingXMLLi_C84D/image_6.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MailMergingaSingleWordDocumentUsingXMLLi_C84D/image_thumb_2.png" width=687 height=385 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MailMergingaSingleWordDocumentUsingXMLLi_C84D/image_thumb_2.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Save the document (I named it Doc1.docx) and then rename the .docx extension to .zip and you can drill into the package and see a bunch of XML documents inside it. If we drill down through the zip file we'll see that the text we just typed is located in the \word\document.xml file. Copy this xml and paste it into the Visual Basic editor, it will infer it as an XDocument object, and then you can use embedded expressions to replace the placeholders. (If I’ve lost you, &lt;A href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx"&gt;read this article which explains it step-by-step&lt;/A&gt;.)&lt;/P&gt;
&lt;P&gt;In order to create letters for our customers in the database, we want to end up with a collection of XDocuments with our data merged into them. I created a simple class called Letter that has two properties, CustomerID As String and Document As XDocument. Then I wrote a LINQ query to select the data and embed it into the document (I’ve omitted all the WordProcessingML for clarity, take a loot at &lt;A href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=openxmlvb&amp;amp;DownloadId=7325" target=_blank mce_href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=openxmlvb&amp;amp;DownloadId=7325"&gt;the code sample&lt;/A&gt; for the whole listing.)&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;letters = _
&lt;SPAN style="COLOR: blue"&gt;    From &lt;/SPAN&gt;Order &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;db.Orders _
&lt;SPAN style="COLOR: blue"&gt;    Join &lt;/SPAN&gt;Employee &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;db.Employees _
&lt;SPAN style="COLOR: blue"&gt;        On &lt;/SPAN&gt;Order.EmployeeID &lt;SPAN style="COLOR: blue"&gt;Equals &lt;/SPAN&gt;Employee.EmployeeID _
&lt;SPAN style="COLOR: blue"&gt;    Where &lt;/SPAN&gt;Order.OrderDate &lt;SPAN style="COLOR: blue"&gt;IsNot Nothing AndAlso &lt;/SPAN&gt;_
        Order.ShippedDate &lt;SPAN style="COLOR: blue"&gt;IsNot Nothing AndAlso &lt;/SPAN&gt;_
        Order.ShippedDate.Value.Date &amp;gt;= #1/1/2007# _
&lt;SPAN style="COLOR: blue"&gt;    Let &lt;/SPAN&gt;DateOrder = Order.OrderDate.Value.ToShortDateString _
&lt;SPAN style="COLOR: blue"&gt;    Let &lt;/SPAN&gt;DateShip = Order.ShippedDate.Value.ToShortDateString _
&lt;SPAN style="COLOR: blue"&gt;    Select New &lt;/SPAN&gt;Letter &lt;SPAN style="COLOR: blue"&gt;With &lt;/SPAN&gt;{ _
        .CustomerID = Order.Customer.CustomerID, _
        .Document = &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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;1.0&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;utf-8&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;yes&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;?&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:document &lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;...&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:p &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00705CFF&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidRDefault&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00112228&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidP&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00AA2EC6&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:br&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;007A5236&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xml:space&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;preserve&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;Dear &lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:proofErr &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:type&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;spellStart&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;&amp;lt;%=&lt;/SPAN&gt; Order.Customer.ContactName &lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:proofErr &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:type&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;spellEnd&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00AA2EC6&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
            &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
     &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:p&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;     &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:p &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00E04FB0&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidRDefault&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00AA2EC6&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidP&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00AA2EC6&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xml:space&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;preserve&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;We’d like to inform you that the order you placed on &lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:proofErr &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:type&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;spellStart&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00112228&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;&amp;lt;%=&lt;/SPAN&gt; DateOrder &lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
            &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:proofErr &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:type&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;spellEnd&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00806521&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xml:space&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;preserve&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;has shipped on &lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
            &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:proofErr &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:type&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;spellStart&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00112228&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;&amp;lt;%=&lt;/SPAN&gt; DateShip &lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
            &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
... &lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:document&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" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The query returns an IEnumerable(Of Letter) objects with the Document property set to the document.xml data for that customer. The next step involved taking the template Doc1.docx file, making a copy of it and then simply replacing the document.xml part inside the package with the one here in the Letter class for each letter. However, what I did was create separate letters for each customer. Instead we want to create one .docx file with &lt;STRONG&gt;ALL&lt;/STRONG&gt; the letter data merged inside. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Merging into a Single Word Document&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The first thing we need to do is insert a page break between all our letters. The easiest thing to do is to open back up your template Doc1.docx file in Word and insert a page break, save it, and then look at the document.xml again in the package. You should see this WordProccessingML element inserted near the end:&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;w:p &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00622A50&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidRDefault&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00622A50&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:br &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:type&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;page&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:p&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" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Paste this into the query above in the document exactly where you pulled it out of the document.xml. &lt;/P&gt;
&lt;P&gt;Next we have a couple options on how to manipulate the package (docx file). I’ve shown &lt;A href="http://blogs.msdn.com/bethmassi/archive/2008/07/30/accessing-openxml-document-parts-with-the-openxml-sdk.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2008/07/30/accessing-openxml-document-parts-with-the-openxml-sdk.aspx"&gt;how to use the Open XML SDK before to manipulate documents&lt;/A&gt; but in this simple case we can use the System.IO.Packaging classes directly. This is because all we’re doing is working with text in the document. If we were working with images or embedded objects it would be easier to use the SDK. In the next post we’ll add photos of the employees on each order into the document, but for this post let’s just focus on how to merge the text. &lt;/P&gt;
&lt;P&gt;So the first thing we need to do is Import some namespaces including an XML namespace that we’re going to use:&lt;/P&gt;&lt;PRE class=code&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:w&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;http://schemas.openxmlformats.org/wordprocessingml/2006/main&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.IO
&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.IO.Packaging&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;Next we need to set up some variables and copy the Doc1.docx template to a new file I’m calling AllLetters.docx.&lt;/P&gt;&lt;PRE class=code&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;"/word/document.xml"&lt;/SPAN&gt;, UriKind.Relative)
&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;contentType = &lt;SPAN style="COLOR: #a31515"&gt;"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;sourceFile = CurDir() &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"\Doc1.docx"
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;letterDir = CurDir() &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"\Letters\"
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;My&lt;/SPAN&gt;.Computer.FileSystem.CreateDirectory(letterDir)

&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;mergeFile = letterDir &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"AllLetters.docx"
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;My&lt;/SPAN&gt;.Computer.FileSystem.CopyFile(sourceFile, mergeFile, &lt;SPAN style="COLOR: blue"&gt;True&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 open the template package and load the main document part as an XElement:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Package = Package.Open(mergeFile)

&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 = p.GetPart(uri)
    &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;mainDocumentXML &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;XElement&lt;BR&gt;
&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;sr &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;StreamReader(mainPart.GetStream)
        mainDocumentXML = XElement.Load(sr)
    &lt;SPAN style="COLOR: blue"&gt;End Using&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;The next part is where it gets fun. A word document has a top element structure like this:&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;w:document&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:body&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
       &lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;...
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:body&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:document&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" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;So what we need to do is grab the body of the template, replace it with the first customer’s document body we have and then append the rest of the elements inside the bodies of the rest of the documents. A word document can only have one &amp;lt;w:body&amp;gt; element for it to be legal. The way we get the &amp;lt;w:body&amp;gt; XElement from the document is using the descendants syntax with the three dot notation (…): &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;    Dim &lt;/SPAN&gt;mainBody = mainDocumentXML...&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;&lt;/SPAN&gt;w:body&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;.First()
    &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;i = 0

    &lt;SPAN style="COLOR: blue"&gt;For Each &lt;/SPAN&gt;letter &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;letters
        &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;nextBody = letter.Document...&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;&lt;/SPAN&gt;w:body&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;.First()
        &lt;SPAN style="COLOR: blue"&gt;If &lt;/SPAN&gt;i = 0 &lt;SPAN style="COLOR: blue"&gt;Then
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'Replace the first body contents in the template
            &lt;/SPAN&gt;mainBody.ReplaceNodes(nextBody.Elements())
        &lt;SPAN style="COLOR: blue"&gt;Else
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'Append the new contents for the rest of the customers
            &lt;/SPAN&gt;mainBody.Add(nextBody.Elements())
        &lt;SPAN style="COLOR: blue"&gt;End If
        &lt;/SPAN&gt;i += 1
    &lt;SPAN style="COLOR: blue"&gt;Next&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Now that we’ve built up the right body with all our letter data in it, we can replace the main document.xml part in the package and close it.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;    'Delete the current document.xml file in the template
    &lt;/SPAN&gt;p.DeletePart(uri)
    &lt;SPAN style="COLOR: green"&gt;'Replace that part with our new merged XDocument
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;replace &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;PackagePart = p.CreatePart(uri, contentType)&lt;BR&gt;
    &lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;sw &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;StreamWriter(replace.GetStream())
        mainDocumentXML.Save(sw)
        sw.Close()
    &lt;SPAN style="COLOR: blue"&gt;End Using

&lt;/SPAN&gt;    p.Close()
&lt;SPAN style="COLOR: blue"&gt;End Using&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Now when we run this, all the letters will be mail merged into the same document for easy printing:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MailMergingaSingleWordDocumentUsingXMLLi_C84D/image_4.png" target=_blank mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MailMergingaSingleWordDocumentUsingXMLLi_C84D/image_4.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MailMergingaSingleWordDocumentUsingXMLLi_C84D/image_thumb_1.png" width=703 height=253 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/MailMergingaSingleWordDocumentUsingXMLLi_C84D/image_thumb_1.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;As I mentioned if we have embedded images or objects that we need to replace it gets a little trickier. In the &lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/08/17/devproconnections-article-taking-advantage-of-linq-and-xml-in-microsoft-office-2007.aspx" mce_href="http://blogs.msdn.com/bethmassi/archive/2009/08/17/devproconnections-article-taking-advantage-of-linq-and-xml-in-microsoft-office-2007.aspx"&gt;DevProConnections Article&lt;/A&gt; I have an example of how to create multiple documents with embedded pictures of the employee’s photo. In the next post I’ll show you how 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 mce_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; to create a single document with embedded pictures as well. &lt;/P&gt;
&lt;P&gt;Until then, have a look &lt;A href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=openxmlvb&amp;amp;DownloadId=7325" target=_blank mce_href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=openxmlvb&amp;amp;DownloadId=7325"&gt;at the complete code I put up on Code Gallery&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;[UPDATE:&amp;nbsp;&lt;A href="http://blogs.msdn.com/bethmassi/archive/2009/09/24/merging-text-photos-into-a-word-document-using-open-xml-sdk.aspx" mce_href="http://blogs.msdn.com/bethmassi/archive/2009/09/24/merging-text-photos-into-a-word-document-using-open-xml-sdk.aspx"&gt;Merging Text &lt;STRONG&gt;&amp;amp; Photos &lt;/STRONG&gt;into a Word Document using Open XML SDK&lt;/A&gt;]&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9898711" 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/LINQ/default.aspx">LINQ</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></item><item><title>DevProConnections Article: Taking Advantage of LINQ and XML in Microsoft Office 2007</title><link>http://blogs.msdn.com/bethmassi/archive/2009/08/17/devproconnections-article-taking-advantage-of-linq-and-xml-in-microsoft-office-2007.aspx</link><pubDate>Mon, 17 Aug 2009 20:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9879123</guid><dc:creator>Beth Massi</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9879123.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9879123</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9879123</wfw:comment><description>&lt;p&gt;This month I have an article on DevProConnections:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;a href="http://www.devproconnections.com/tabId/180/itemId/4575/Taking-Advantage-of-LINQ-and-XML-in-Microsoft-Offi.aspx" target="_blank"&gt;Taking Advantage of LINQ and XML in Microsoft Office 2007&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In this article, I talk about how a lot of applications that need to take advantage of Microsoft Office can do so without going through COM. Many programs that need to process documents often require manipulation of the file formats directly and doing that through the Office component object model won’t scale very well. It also requires that Microsoft Office be installed to run. A better route in a lot of these cases is to 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;. With the release of Office 2007, Word documents, Excel spreadsheets and PowerPoint presentations are based on an open standard for packaging XML files called Open XML. Using Visual Basic’s powerful and simple implementation of LINQ to XML you can work with these new document formats much easier than ever before.&lt;/p&gt;  &lt;p&gt;I show a couple practical examples of reading data from Word documents and updating a database as well as reading data from a database to create Word documents – all without COM. No Office applications need to be installed in order to read and write to these formats directly.&amp;#160; &lt;/p&gt;  &lt;p&gt;This article is based on the two episodes I did on DnrTV:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/04/07/dnrtv-showing-off-the-open-xml-sdk-and-linq.aspx"&gt;dnrTV: Showing off the Open XML SDK and LINQ&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/04/20/dnrtv-more-fun-with-office-and-xml-literals.aspx"&gt;dnrTV: More Fun with Office and XML Literals&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;[UPDATE: Here's code samples (also includes a presentation pptx)] &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://code.msdn.microsoft.com/openxmlvb"&gt;Working with Open XML in Visual Basic&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;More resources:&lt;/p&gt;  &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c6e744e5-36e9-45f5-8d8c-331df206e0d0&amp;amp;DisplayLang=en"&gt;Open XML Format SDK 2.0&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/office/bb265236.aspx"&gt;Open XML Resource Center&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=46B6BF86-E35D-4870-B214-4D7B72B02BF9&amp;amp;displaylang=en"&gt;Microsoft Visual Studio Tools for the Office System Power Tools v1.0.0.0&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.codeplex.com/dbe"&gt;Word 2007 Content Control Toolkit &lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://msdn.com/vsto"&gt;VSTO Developer Center&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://msdn.com/vbasic"&gt;Visual Basic Developer Center&lt;/a&gt;     &lt;p&gt;Enjoy!&lt;/p&gt;    &lt;p&gt;&lt;/p&gt; &lt;/li&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9879123" 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/LINQ/default.aspx">LINQ</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></item><item><title>Filtering Entity Framework Collections in Master-Detail Forms</title><link>http://blogs.msdn.com/bethmassi/archive/2009/07/16/filtering-entity-framework-collections-in-master-detail-forms.aspx</link><pubDate>Fri, 17 Jul 2009 03:18:17 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9836309</guid><dc:creator>Beth Massi</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9836309.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9836309</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9836309</wfw:comment><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/07/14/master-detail-data-binding-in-wpf-with-entity-framework.aspx" target="_blank"&gt;Last post&lt;/a&gt; I talked about how to get WPF data binding to work with master-detail entity collections. I had a couple readers ask me how they could filter the child collection instead of bringing them all down so in this post I’d like to show how you could do that. It’s actually pretty easy.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Customer (Master) –&amp;lt; Orders (Detail) &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I created a very simple Entity Data Model (EDM) that demonstrates a Master-Detail relationship. The Orders table is defined in the database with a non-nullable foreign key CustomerID, meaning that no Order can exist without a Customer. This relationship is inferred by Entity Framework (EF) to set up the navigation properties giving us an Orders EntityCollection on Customer. &lt;/p&gt;  &lt;p&gt;&lt;img src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/DataBindingWPFLookupComboboxValuestoEFEn_F345/image_6.png" /&gt;&lt;/p&gt;  &lt;p&gt;To recap, I’ve created my own ObservableCollection(of Customer) called CustomerCollection so that when the UI modifies the collection through AddItem/RemoveItem, we can instruct the ObjectContext to track these changes so that it will insert and delete entities to the database when we call SaveChanges. &lt;/p&gt;  &lt;p&gt;The constructor takes an IEnumerable(Of Customer) which allows us to pass a LINQ to Entities query into our CustomerCollection. This executes the query against the database when we call the base class’s constructor which iterates over the query results and adds the Customer entities to our collection. &lt;/p&gt;  &lt;p&gt;Take a look &lt;a href="http://blogs.msdn.com/bethmassi/archive/2009/07/14/master-detail-data-binding-in-wpf-with-entity-framework.aspx" target="_blank"&gt;at the first chunk of code in the last post&lt;/a&gt; for the full code listing for the CustomerCollection class. I don’t have to make any changes to it to support filtering the children. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Loading All Detail Entities &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you want to bring down all the Orders for the selected Customer you can use the .Include extension like I’ve shown before using explicit loading. &lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: green"&gt;'EF ObjectContext connects to database and tracks changes
&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;OMSEntities
&lt;span style="color: green"&gt;'inherits from ObservableCollection(Of Customer)
&lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;CustomerData &lt;span style="color: blue"&gt;As &lt;/span&gt;CustomerCollection

&lt;span style="color: green"&gt;'Include all Orders for Customer #1
&lt;/span&gt;&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;db.Customers.Include(&lt;span style="color: #a31515"&gt;&amp;quot;Orders&amp;quot;&lt;/span&gt;) _
                &lt;span style="color: blue"&gt;Where &lt;/span&gt;c.CustomerID = 1

CustomerData = &lt;span style="color: blue"&gt;New &lt;/span&gt;CustomerCollection(customers, db)&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;This ends up shooting one query to SQL Server to return all the Orders for the selected Customer when we pass the query into our collection. But what if we also wanted to filter the Orders? There’s a couple ways we can do this because of a cool feature of the Entity Framework. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filtering Detail Entities with a Sub-Query&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the entities are being created in memory on the client from the query (materialized), the object state manager will attempt to hook up the entity references and collections automatically. This means that all we have to do is specify a filtered query and make sure we execute it by enumerating over the results (or calling ToList). &lt;/p&gt;

&lt;p&gt;So say we wanted to only grab the most recent Orders where the order was placed on or after January 1st, 2009:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;query = &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.CustomerID = 1 _
            &lt;span style="color: blue"&gt;Select &lt;/span&gt;Customer = c, _
&lt;strong&gt;                   Orders = &lt;span style="color: blue"&gt;From &lt;/span&gt;o &lt;span style="color: blue"&gt;In &lt;/span&gt;c.Orders _
                            &lt;span style="color: blue"&gt;Where &lt;/span&gt;o.OrderDate &amp;gt;= #1/1/2009#
&lt;/strong&gt;
&lt;span style="color: blue"&gt;Dim &lt;/span&gt;customers = &lt;span style="color: blue"&gt;From &lt;/span&gt;item &lt;span style="color: blue"&gt;In &lt;/span&gt;&lt;strong&gt;query.ToList&lt;/strong&gt; &lt;span style="color: blue"&gt;Select &lt;/span&gt;item.Customer

CustomerData = &lt;span style="color: blue"&gt;New &lt;/span&gt;CustomerCollection(customers, db)&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Here I’m specifying a sub-query to only pull the Orders I want on the selected Customer. The first query creates a collection of anonymous types that have a Customer object and a filtered Orders collection. In the following query, I need to call query.ToList in order to execute the query against the database and materialize the objects. This sends one statement to SQL Server like before, but this time it’s filtered on Orders as well.&lt;/p&gt;

&lt;p&gt;At this point the Customers and Orders are in memory and the object state manager has hooked them up for us. Meaning that the Customer now has an Orders collection like we want. As long as we Select the entire Customer and Order types in our queries this will work (as opposed to just selecting specific fields – the entity types have to match up for it to work). The second query is just a LINQ to Objects query (in memory) that we’re using so that we can pass an IEnumerable(Of Customer) to our ObservableCollection. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filtering Detail Entities with &lt;/strong&gt;&lt;strong&gt;Separate Queries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are other ways we could write this. We could write the queries separately:&lt;/p&gt;

&lt;pre class="code"&gt;&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;db.Customers _
                 &lt;span style="color: blue"&gt;Where &lt;/span&gt;c.CustomerID = 1).ToList()

&lt;span style="color: blue"&gt;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;db.Orders _
              &lt;span style="color: blue"&gt;Where &lt;/span&gt;o.Customer.CustomerID = 1 &lt;span style="color: blue"&gt;AndAlso &lt;/span&gt;_
                    o.OrderDate &amp;gt; #1/1/2009#).ToList()

CustomerData = &lt;span style="color: blue"&gt;New &lt;/span&gt;CustomerCollection(customers, db)&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Notice that I’m calling ToList to force the queries to execute so that the objects will materialize (come into memory), then I’m just passing the Customers to the constructor because at this point the object state manager has hooked up our entities (Customer has an EntityCollection of Orders based on the filtered query). The results on the client are the same but the major difference here is that &lt;strong&gt;two &lt;/strong&gt;statements are sent to SQL Server, so keep that in mind. I like the first approach better with a sub-query because of the single SQL statement that’s generated as well as the clearer looking LINQ query.&lt;/p&gt;

&lt;p&gt;I’ve updated &lt;a href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=wpfdatavideos&amp;amp;DownloadId=6509" target="_blank"&gt;this &lt;strong&gt;sample application&lt;/strong&gt;&lt;/a&gt; that also shows a variety of other data binding techniques with EF and WPF so have a look. The filter example above is in the SimpleMasterDetailBinding form.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9836309" 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/LINQ/default.aspx">LINQ</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/Entity+Framework/default.aspx">Entity Framework</category></item><item><title>Using the WPF ObservableCollection with EF Entities</title><link>http://blogs.msdn.com/bethmassi/archive/2009/05/08/using-the-wpf-observablecollection-with-ef-entities.aspx</link><pubDate>Sat, 09 May 2009 01:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9597952</guid><dc:creator>Beth Massi</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9597952.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9597952</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9597952</wfw:comment><description>&lt;P&gt;The &lt;A href="http://msdn.microsoft.com/en-us/library/ms668604.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms668604.aspx"&gt;ObservableCollection&lt;/A&gt; is a special WPF collection that provides proper notifications to the UI when items are added, removed, or the list is refreshed because it implements &lt;A href="http://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged.aspx"&gt;INotifyCollectionChanged&lt;/A&gt;. It’s common to use this collection (or inherit from it) to contain your business objects you want to bind to in WPF.&amp;nbsp; &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Class &lt;/SPAN&gt;Window1&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;    Private &lt;/SPAN&gt;CustomerData &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;ObservableCollection(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Customer)&lt;/PRE&gt;
&lt;P&gt;You can then set up a &lt;A href="http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.aspx"&gt;CollectionViewSource&lt;/A&gt; and use it’s View property to get a reference to the &lt;A href="http://msdn.microsoft.com/en-us/library/system.windows.data.listcollectionview.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/system.windows.data.listcollectionview.aspx"&gt;ListCollectionView&lt;/A&gt; in order to add and remove items instead of working with the source collection directly. This decouples your data source (and therefore any collection logic) from the form itself making it much easier to change sources later. I’ve showed &lt;A href="http://blogs.msdn.com/bethmassi/archive/2008/11/07/loading-data-and-binding-controls-in-wpf-with-collectionviewsource.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2008/11/07/loading-data-and-binding-controls-in-wpf-with-collectionviewsource.aspx"&gt;how to use CollectionViewSources before&lt;/A&gt; but basically you just declare them in the Window.Resources section and bind to them in 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;="Window1"
    &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;="Window1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="282" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="440" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Window1"&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window.Resources&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
      &lt;STRONG&gt;  &amp;lt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: #a31515"&gt;CollectionViewSource &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;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;="CustomerSource" /&amp;gt;&lt;/STRONG&gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window.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;DataContext&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: red"&gt;Source&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;CustomerSource&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;STRONG&gt;}&lt;/STRONG&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;And then you can set the Source property in code to your collection and obtain the ListCollectionView. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;customerSource = &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;"CustomerSource"&lt;/SPAN&gt;), CollectionViewSource)
customerSource.&lt;STRONG&gt;Source&lt;/STRONG&gt; = &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.CustomerData

&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(customerSource.&lt;STRONG&gt;View&lt;/STRONG&gt;, ListCollectionView)&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;Then you use the View to add and remove items from the collection and the UI will update properly: &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 Me&lt;/SPAN&gt;.View.CurrentPosition &amp;gt; -1 &lt;SPAN style="COLOR: blue"&gt;Then
           &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'removes the currently selected customer from the underlying collection 
           &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View.RemoveAt(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View.CurrentPosition)
       &lt;SPAN style="COLOR: blue"&gt;End If
   End Sub

   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;'adds a new customer to the underlying collection 
       &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;customer = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View.AddNew, Customer)
       &lt;SPAN style="COLOR: green"&gt;'do something with customer if needed...
       &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View.CommitNew()
   &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;Calling these methods on the ListCollectionView will execute the &lt;A href="http://msdn.microsoft.com/en-us/library/ms654928.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms654928.aspx"&gt;InsertItem&lt;/A&gt; and &lt;A href="http://msdn.microsoft.com/en-us/library/ms654938.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms654938.aspx"&gt;RemoveItem&lt;/A&gt; methods on the ObservableCollection.&lt;/P&gt;
&lt;P&gt;Now if you are using an &lt;A href="http://msdn.microsoft.com/en-us/library/bb387122.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb387122.aspx"&gt;Entity Data Model (EDM)&lt;/A&gt; the designer in Visual Studio 2008 SP1 will generate entity classes for you that you can also bind to in your UI. Access to these entities is done through the &lt;A href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx"&gt;ObjectContext&lt;/A&gt; and the designer also creates a class for you that inherits from this when you create the EDM. It is named something like xxxEntites. (For instance, in Visual Studio 2008 SP1 “Add New Item” and select ADO.NET Entity Data Model and name it Northwind.edmx. Generate from Database and select Northwind. Select all the tables and then the designer will generate an ObjectContext called NorthwindEntities and entity classes based on the tables in the database.)&lt;/P&gt;
&lt;P&gt;Because the ObjectContext is what tracks changes on entities you can place entities inside an ObservableCollection but in order for the ObjectContext to be notified that adds and deletes need to be tracked you need to write a bit of code. The easiest thing to do is to create your own class that inherits from ObservableCollection and override the InsertItem and RemoveItem methods so that you can tell the ObjectContext to either add or delete the entity which will ultimately execute against the database. In the constructor pass a reference to the ObjectContext. You can also pass in any collection of entities, say from a LINQ query, and then add them to the ObservableCollection. For example:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;NorthwindDAL
&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.Collections.ObjectModel

&lt;SPAN style="COLOR: blue"&gt;Public Class &lt;/SPAN&gt;CustomerCollection
    &lt;SPAN style="COLOR: blue"&gt;Inherits &lt;/SPAN&gt;ObservableCollection(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Customer)

   &lt;SPAN style="COLOR: blue"&gt; Private &lt;/SPAN&gt;_context &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;NorthwindEntities
    &lt;SPAN style="COLOR: blue"&gt;Public ReadOnly Property &lt;/SPAN&gt;Context() &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;NorthwindEntities
        &lt;SPAN style="COLOR: blue"&gt;Get
            Return &lt;/SPAN&gt;_context
        &lt;SPAN style="COLOR: blue"&gt;End Get
    End Property

    Sub New&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;customers &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;IEnumerable(&lt;SPAN style="COLOR: blue"&gt;Of &lt;/SPAN&gt;Customer), &lt;SPAN style="COLOR: blue"&gt;ByVal &lt;/SPAN&gt;context &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;NorthwindEntities)
        &lt;SPAN style="COLOR: blue"&gt;MyBase&lt;/SPAN&gt;.New(customers)&lt;BR&gt;       &lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;_context = context
    &lt;SPAN style="COLOR: blue"&gt;End Sub

    Protected Overrides Sub &lt;/SPAN&gt;InsertItem(&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;ByVal &lt;/SPAN&gt;item &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Customer)
   &lt;SPAN style="COLOR: blue"&gt;     Me&lt;/SPAN&gt;.Context.AddToCustomers(item)
   &lt;SPAN style="COLOR: blue"&gt;     MyBase&lt;/SPAN&gt;.InsertItem(index, item)
    &lt;SPAN style="COLOR: blue"&gt;End Sub

    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;Me&lt;/SPAN&gt;.Context.DeleteObject(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;(index))
        &lt;SPAN style="COLOR: blue"&gt;MyBase&lt;/SPAN&gt;.RemoveItem(index)
    &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;Then you can use the collection on your WPF form instead like so:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;NorthwindDAL

&lt;SPAN style="COLOR: blue"&gt;Class &lt;/SPAN&gt;Window1
    &lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;db &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;NorthwindEntities
    &lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;CustomerData &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;CustomerCollection
    &lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;View &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;ListCollectionView

    &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;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;db.Customers _
                      &lt;SPAN style="COLOR: blue"&gt;Where &lt;/SPAN&gt;c.City.ToLower = &lt;SPAN style="COLOR: #a31515"&gt;"seattle" &lt;/SPAN&gt;_
                      &lt;SPAN style="COLOR: blue"&gt;Order By &lt;/SPAN&gt;c.LastName, c.FirstName _
                      &lt;SPAN style="COLOR: blue"&gt;Select &lt;/SPAN&gt;c

&lt;STRONG&gt;        &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.CustomerData = &lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;CustomerCollection(results, db)&lt;/STRONG&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;        &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;customerSource = &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;"CustomerSource"&lt;/SPAN&gt;), CollectionViewSource)
        customerSource.Source = &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.CustomerData
        &lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(customerSource.View, ListCollectionView)
    &lt;SPAN style="COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&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
            &lt;/SPAN&gt;db.SaveChanges()
            MsgBox(&lt;SPAN style="COLOR: #a31515"&gt;"Customer 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;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 Me&lt;/SPAN&gt;.View.CurrentPosition &amp;gt; -1 &lt;SPAN style="COLOR: blue"&gt;Then
&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View.RemoveAt(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View.CurrentPosition)
        &lt;SPAN style="COLOR: blue"&gt;End If
    End Sub

    Private Sub &lt;/SPAN&gt;btnAdd_Click() &lt;SPAN style="COLOR: blue"&gt;Handles &lt;/SPAN&gt;btnAdd.Click
&lt;SPAN style="COLOR: blue"&gt;        Dim &lt;/SPAN&gt;customer = &lt;SPAN style="COLOR: blue"&gt;CType&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View.AddNew, Customer)
        &lt;SPAN style="COLOR: green"&gt;'do something with customer if needed...
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.View.CommitNew()
    &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;SPAN style="COLOR: blue"&gt;End Class&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Now any updates, adds or deletes you make in the UI will be propagated to the database through the Entity Framework.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9597952" 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/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></item><item><title>Data Binding WPF Lookup Combobox Values to EF Entities</title><link>http://blogs.msdn.com/bethmassi/archive/2009/04/30/data-binding-wpf-lookup-combobox-values-to-ef-entities.aspx</link><pubDate>Thu, 30 Apr 2009 17:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9576176</guid><dc:creator>Beth Massi</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9576176.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9576176</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9576176</wfw:comment><description>&lt;p&gt;It’s extremely common to have to hook up lookup tables on your data entry forms in order to populate foreign keys in a database. I’ve talked about how to do this in Winforms and WPF with Datasets and LINQ to SQL before:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/cc788742.aspx" target="_blank"&gt;How Do I: Create a Lookup Combobox in WPF?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/dd239277.aspx" target="_blank"&gt;How Do I: Create a Master-Detail Data Entry Form in WPF?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/bb643829.aspx" target="_blank"&gt;How Do I: Create Lookup Lists?&lt;/a&gt;&amp;#160; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/02/07/creating-lookup-lists-with-linq-to-sql.aspx"&gt;Creating Lookup Lists with LINQ to SQL&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/02/06/related-data-binding-and-comboboxes-with-linq-to-sql.aspx"&gt;Related Data Binding and ComboBoxes with LINQ to SQL&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/bethmassi/archive/2007/04/25/tips-on-related-data-binding-and-comboboxes.aspx"&gt;Tips on Related Data Binding and ComboBoxes&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The common theme between all of these is that the data sources, either the LINQ to SQL classes or the DataTables that we bind to, uses a navigation path based on the foreign key and that foreign key is exposed as a property (or DataColumn). For instance if we have a Customer related to Orders we would have a CustomerID property on Orders. &lt;/p&gt;  &lt;p&gt;DataSets (like databases) rely on this type of navigation. So when you want to find the parent Customer of an Order you have to know the relation. Using typed datasets helps you more but you still end up having to know the details of relationships and foreign keys of the DataSet. That’s why people who are familiar with databases are usually comfortable with working with DataSets.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/DataBindingWPFLookupComboboxValuestoEFEn_F345/image_2.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="236" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/DataBindingWPFLookupComboboxValuestoEFEn_F345/image_thumb.png" width="587" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;LINQ to SQL classes also include navigation properties as direct object references and collections. So they have both the foreign key and the navigation properties. Customer will have a collection of Orders and Order will have a reference back to Customer but the classes also contain the CustomerID property. This isn’t “pure” I suppose but it does make data binding and subsequent saves back to the database pretty much a no brainer. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/DataBindingWPFLookupComboboxValuestoEFEn_F345/image_4.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="242" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/DataBindingWPFLookupComboboxValuestoEFEn_F345/image_thumb_1.png" width="553" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;For instance say I want to hook up a lookup combobox using a LINQ to SQL class on an Order with a reference to Customer. I want to display a list of Customers the user can pick from and that Customer should be associated with that Order. It’s pretty straight forward and works the same with DataTables.&lt;/p&gt;  &lt;p&gt;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.Resources&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CollectionViewSource &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;OrdersSource&amp;quot; /&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CollectionViewSource &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;CustomerLookup&amp;quot; /&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Window.Resources&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;pre class="code"&gt;&lt;span style="color: blue"&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;1&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Grid1&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;DataContext&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;Source&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;OrdersSource&lt;/span&gt;&lt;span style="color: blue"&gt;}}&amp;quot;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;lt;ComboBox &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;23&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ComboBox1&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;177&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Margin&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;2&amp;quot;  &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Left&amp;quot; 
          &lt;/span&gt;&lt;span style="color: red"&gt;IsEditable&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;False&amp;quot;
          &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;Source&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;CustomerLookup&lt;/span&gt;&lt;span style="color: blue"&gt;}}&amp;quot;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: red"&gt;          DisplayMemberPath&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;LastName&amp;quot;&lt;br /&gt;&lt;span style="color: red"&gt;          SelectedValuePath&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;CustomerID&amp;quot; &lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;          &lt;/span&gt;&lt;span style="color: red"&gt;SelectedValue&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;=CustomerID}&amp;quot; 
          &lt;/span&gt;&lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;...&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Code-behind:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Class &lt;/span&gt;Window1
    &lt;span style="color: blue"&gt;Private &lt;/span&gt;db &lt;span style="color: blue"&gt;As New &lt;/span&gt;MyDataObjectContext
    &lt;span style="color: blue"&gt;Private &lt;/span&gt;OrderData &lt;span style="color: blue"&gt;As &lt;/span&gt;IEnumerable(&lt;span style="color: blue"&gt;Of &lt;/span&gt;Order)

    &lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;Window1_Loaded(&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.Windows.RoutedEventArgs) &lt;span style="color: blue"&gt;Handles Me&lt;/span&gt;.Loaded
        &lt;span style="color: green"&gt;'Load all the orders from the database
        &lt;/span&gt;&lt;span style="color: blue"&gt;Me&lt;/span&gt;.OrderData = db.Orders
        &lt;span style="color: green"&gt;'Get the customer lookup list (this is the Combobox ItemsSource)
        &lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;customerList = &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.Orders.Count &amp;gt; 0 _
                           &lt;span style="color: blue"&gt;Order By &lt;/span&gt;c.LastName, c.FirstName

        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;ordersSource = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.FindResource(&lt;span style="color: #a31515"&gt;&amp;quot;OrdersSource&amp;quot;&lt;/span&gt;), CollectionViewSource)
        ordersSource.Source = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.OrderData
        &lt;span style="color: blue"&gt;Dim &lt;/span&gt;custSource = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.FindResource(&lt;span style="color: #a31515"&gt;&amp;quot;CustomerLookup&amp;quot;&lt;/span&gt;), CollectionViewSource)
        custSource.Source = customerList.ToList()

    &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;Almost all of this code is just to set up the context of this discussion, you can &lt;a href="http://msdn.microsoft.com/en-us/vbasic/dd239277.aspx" target="_blank"&gt;watch this video for details&lt;/a&gt; on building a complete example. Here I’m using CollectionViewSources in the XAML and setting their Source property in code. This technique is handy especially if you are using nested DataTemplates. The important piece to note are the four properties on the Combobox. ItemsSource, DisplayMemberPath, SelectedValue, and SelectedValuePath. To set up your combobox:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Set the ItemsSource to the list of Customers you want to display in the Combobox.&amp;#160; &lt;/li&gt;

  &lt;li&gt;Next set the DisplayMemberPath to the property name on this list that you want to use to display in the list, here I used LastName. &lt;/li&gt;

  &lt;li&gt;Then set the &lt;strong&gt;SelectedValuePath &lt;/strong&gt;to the property name on this list that will be used to populate the foreign key value on the Order. &lt;/li&gt;

  &lt;li&gt;Finally you set the &lt;strong&gt;SelectedValue&lt;/strong&gt; to the property binding on the Order that is foreign key. LINQ to SQL (and DataSets) will happily save your data with this binding in place. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is how you always bind DataTables and it also works well for LINQ to SQL classes. But since LINQ to SQL classes also include the navigation properties (the Orders collection on Customer and the Customer object reference on Order) you can use a different technique by binding directly to the Customer reference. This is the only choice we have with Entity Framework entities in .NET 3.5 SP1. &lt;/p&gt;

&lt;p&gt;What’s unique with Entity Framework is that the associations between other entities use &lt;strong&gt;only &lt;/strong&gt;navigation properties -- so there isn’t a CustomerID foreign key property value on the Order at all. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/DataBindingWPFLookupComboboxValuestoEFEn_F345/image_6.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="279" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/DataBindingWPFLookupComboboxValuestoEFEn_F345/image_thumb_2.png" width="448" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;What you have to do instead is &lt;strong&gt;bind directly to the Customer &lt;/strong&gt;object reference. The change in the above example is the Combobox binding in 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;ComboBox &lt;/span&gt;&lt;span style="color: red"&gt;Height&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;23&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ComboBox1&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;177&amp;quot; &lt;/span&gt;&lt;span style="color: red"&gt;Margin&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;2&amp;quot;  &lt;/span&gt;&lt;span style="color: red"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Left&amp;quot; 
          &lt;/span&gt;&lt;span style="color: red"&gt;IsEditable&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;False&amp;quot;
          &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;Source&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;CustomerLookup&lt;/span&gt;&lt;span style="color: blue"&gt;}}&amp;quot;
&lt;span style="color: red"&gt;          DisplayMemberPath&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;LastName&amp;quot;&lt;/span&gt;          &lt;br /&gt;&lt;/span&gt;&lt;span style="color: red"&gt;          SelectedItem&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;=Customer}&amp;quot; 
          &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;The important pieces in this case are the three properties on the Combobox. ItemsSource, DisplayMemberPath, and &lt;strong&gt;SelectedItem&lt;/strong&gt;. &lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Set the ItemsSource to the list of Customers you want to display in the Combobox -- same as before. &lt;/li&gt;

  &lt;li&gt;Next set the DisplayMemberPath to the property name on this list that you want to use to display in the list, here I used LastName – same as before. &lt;/li&gt;

  &lt;li&gt;Now set the &lt;strong&gt;SelectedItem&lt;/strong&gt; to the property binding on the Order that is the &lt;strong&gt;navigation property to Customer&lt;/strong&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will work properly with LINQ to SQL classes and Entity Framework entities but there is one caveat. You need to make sure that you pull the &lt;strong&gt;entire Customer entity &lt;/strong&gt;into in the lookup list &lt;strong&gt;from the same ObjectContext &lt;/strong&gt;you used to query the Orders. This is because the same ObjectContext (DataContext in LINQ to SQL) needs to resolve the entity references between the queries. Entity Framework does this based on the EntityKeys. The neat side effect of this with EF is that you don’t have to pull down the Customers with the Orders query, they will automatically become references when the Customer lookup list is queried through the same context. (See &lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/12/10/master-details-with-entity-framework-explicit-load.aspx" target="_blank"&gt;my post on explicit load for more details&lt;/a&gt; on how to bring down related EF entities when you only make one call.)&lt;/p&gt;

&lt;p&gt;This behavior may be desired in a lot of scenarios but if we do not need to modify the Customer, like in our example, this can be overkill especially if the Customer has a lot of large fields you aren’t using. In the first example we could have only pulled a subset of fields from the Customer table – the only required ones would be the ones used in the data binding, CustomerID and LastName. So with DataTables and LINQ to SQL classes that bind on the values we could have optimized our lookup list query to:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;customerList = &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.Orders.Count &amp;gt; 0 _
                   &lt;span style="color: blue"&gt;Order By &lt;/span&gt;c.LastName, c.FirstName _
                   &lt;span style="color: blue"&gt;Select &lt;/span&gt;c.CustomerID, c.LastName&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;This &lt;strong&gt;will not work &lt;/strong&gt;if we bind directly to the navigation properties because the customerList is now a list of anonymous types and not a list of Customer entities. So binding to the values gives you greater flexibility with your lookup list queries. Unfortunately in the current version of EF you cannot bind this way but they are planning to enable this in the next version. In .NET 4.0 the EF team will add support for a new type of association called &amp;quot;FK Associations&amp;quot;. &lt;a href="http://blogs.msdn.com/efdesign/archive/2009/03/16/foreign-keys-in-the-entity-framework.aspx" target="_blank"&gt;Read more about that here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And I’m working on the next set of &lt;a href="http://msdn.microsoft.com/en-us/vbasic/bb466226.aspx#wpfdata" target="_blank"&gt;WPF Forms over Data How Do I videos&lt;/a&gt;, this time with Entity Framework, that will hopefully explain how to use EF in practical way by building WPF data applications. Stay tuned!&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9576176" 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/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></item><item><title>Tally Rows in a DataSet that Match a Condition</title><link>http://blogs.msdn.com/bethmassi/archive/2009/04/27/tally-rows-in-a-dataset-that-match-a-condition.aspx</link><pubDate>Tue, 28 Apr 2009 05:24:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9572773</guid><dc:creator>Beth Massi</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9572773.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9572773</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9572773</wfw:comment><description>&lt;p&gt;Today I got a question that comes up often in data application programming about how to count rows in a DataSet that matched a condition. The DataSet may be bound to a DataGridView or other list control and it’s tempting to start looking at the control to see if you can coax it into returning what you need but usually there is a much better way.&lt;/p&gt;  &lt;p&gt;For instance, say we have a table in our database called “Inbox” that has varchar fields Subject, From, and Status and we’d like to tally all the rows where the Status = “Unread”. Suppose we’ve also created a typed DataSet that contains this Inbox table. You create a data-bound Windows Form with a DataGridView on it by dragging the table from the Data sources window onto the form (&lt;a href="http://msdn.microsoft.com/en-us/vbasic/bb725824.aspx"&gt;like I showed in this video&lt;/a&gt;). When you do this, Visual Studio generates code that hooks up your DataGridView’s DataSource property to a BindingSource object which in turn has it’s DataSource set to your DataSet. This is a good thing. The BindingSource is a simple controller that provides currency between your DataSet and the DataGidView UI. (In WPF this is similar to the CollectionView object). You write code against the BindingSource instead so that it doesn’t matter what kind of control is being used to display the data.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;BindingSource to the Rescue&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The BindingSource in this case is actually working with a DataView, not the actual DataTable, which may seem confusing. This is needed for related data binding to work (see &lt;a href="http://msdn.microsoft.com/en-us/vbasic/bb643827.aspx"&gt;this video&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/vbasic/cc138241.aspx"&gt;this one&lt;/a&gt;). Since the BindingSource manages the currency (current row position) that is being displayed by the controls, in this example the BindingSource.List will return the DataView and the BindingSource.Current property will always return the DataRowView. You access your typed DataRow by casting the DataRowView.Row property. So to get a count of items in the DataView we could just simply ask the BindingSource for a count of it’s rows no matter what kind of control is being used for the display:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;count = &lt;span style="color: blue"&gt;Me&lt;/span&gt;.InboxBindingSource.Count&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Or we could grab the DataView and ask for its count:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;dv = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.InboxBindingSource.List, DataView)
&lt;span style="color: blue"&gt;Dim &lt;/span&gt;count = dv.Count&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Once you have the DataView you can apply more filtering on it directly or we can loop through it to tally the rows where Status = “Unread”. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;dv = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.InboxBindingSource.List, DataView)
&lt;span style="color: blue"&gt;Dim &lt;/span&gt;count = 0
&lt;span style="color: blue"&gt;For Each &lt;/span&gt;drv &lt;span style="color: blue"&gt;As &lt;/span&gt;DataRowView &lt;span style="color: blue"&gt;In &lt;/span&gt;dv
    &lt;span style="color: blue"&gt;Dim &lt;/span&gt;inboxRow = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(drv.Row, EmailDataSet.InboxRow)
    &lt;span style="color: blue"&gt;If &lt;/span&gt;inboxRow.Status = &lt;span style="color: #a31515"&gt;&amp;quot;Unread&amp;quot; &lt;/span&gt;&lt;span style="color: blue"&gt;Then
        &lt;/span&gt;count += 1
    &lt;span style="color: blue"&gt;End If
Next&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;But the neat thing about using the BindingSource is that you always know the current row being displayed. So if we want to tally the rows based on a condition in the current row we go through the BindingSource. You can easily write the code that gets the current row as your typed data row by using a code snippet. Right-click in the editor, select Data – LINQ, XML, Designer, ADO.NET &amp;gt; Designer Features and ADO.NET &amp;gt; Converts BindingSource.Current to a specific row in a DataTable:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/TallyRowsinaDataSetthatMatchaCondition_110E1/image_4.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="211" alt="image" src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/TallyRowsinaDataSetthatMatchaCondition_110E1/image_thumb_1.png" width="709" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This code returns a tally of rows in the current view that have the same status as the selected row. Instead of looping through the data manually with For Each, this code sets the Filter property of the DataView instead:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;currentRow &lt;span style="color: blue"&gt;As &lt;/span&gt;EmailDataSet.InboxRow
currentRow = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.InboxBindingSource.Current, DataRowView).Row, EmailDataSet.InboxRow)

&lt;span style="color: blue"&gt;Dim &lt;/span&gt;dv = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.InboxBindingSource.List, DataView)
dv.RowFilter = &lt;span style="color: #a31515"&gt;&amp;quot;Status ='&amp;quot; &lt;/span&gt;&amp;amp; currentRow.Status &amp;amp; &lt;span style="color: #a31515"&gt;&amp;quot;'&amp;quot;
&lt;/span&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;count = dv.Count&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;This technique causes any bound controls to update to the new filter. To remove the filter, set the Filter property to Nothing or the empty string. Although this code may work for a lot of scenarios, we may have a situation where we do not want to affect any of the bound controls by changing the filter. And even though this is a simple condition it would be nice not to have to manually write the loop ourselves. This is a perfect place to use LINQ instead. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LINQ to the Rescue&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we want to tally the entire DataTable for rows matching a condition we can use LINQ to DataSets with Visual Basic’s Aggregate clause. This doesn’t involve a BindingSource at all but be aware that the DataView that a BindingSource may be displaying data from may be filtered. In the case of this example the DataView contains the same rows as the DataTable (no filter) so we can write a simple Aggregate query to count the rows:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;count &lt;span style="color: blue"&gt;As Integer &lt;/span&gt;= &lt;span style="color: blue"&gt;Aggregate &lt;/span&gt;row &lt;span style="color: blue"&gt;In Me&lt;/span&gt;.EmailDataSet.Inbox _
                       &lt;span style="color: blue"&gt;Where &lt;/span&gt;row.Status = &lt;span style="color: #a31515"&gt;&amp;quot;Unread&amp;quot; &lt;/span&gt;_
                       &lt;span style="color: blue"&gt;Into &lt;/span&gt;UnreadCount = Count()&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;This will return an integer indicating the number of rows in the entire DataTable that matched the Where clause. But what if we do want to use the BindingSource and take into account any filters that are being applied to the DataView in which controls are bound? In this case we can still use an Aggregate LINQ query it will just be against the DataView so we will need to cast a few things:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Dim &lt;/span&gt;dv = &lt;span style="color: blue"&gt;CType&lt;/span&gt;(&lt;span style="color: blue"&gt;Me&lt;/span&gt;.InboxBindingSource.List, DataView)
&lt;span style="color: blue"&gt;Dim &lt;/span&gt;count &lt;span style="color: blue"&gt;As Integer &lt;/span&gt;= &lt;span style="color: blue"&gt;Aggregate &lt;/span&gt;row &lt;span style="color: blue"&gt;In &lt;/span&gt;dv.Cast(&lt;span style="color: blue"&gt;Of &lt;/span&gt;DataRowView).AsQueryable _
                       &lt;span style="color: blue"&gt;Where CType&lt;/span&gt;(row.Row, EmailDataSet.InboxRow).Status = &lt;span style="color: #a31515"&gt;&amp;quot;Unread&amp;quot; &lt;/span&gt;_
                       &lt;span style="color: blue"&gt;Into &lt;/span&gt;UnreadCount = Count()&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Now what would be really nice is to automatically tally this information from the DataSet and display it in a label on the Form anytime the user made any changes to the rows. We can do this easily by handling the BindingSource’s ListChanged event and putting our Aggregate LINQ query in there:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;Private Sub &lt;/span&gt;InboxBindingSource_ListChanged() &lt;span style="color: blue"&gt;Handles &lt;/span&gt;InboxBindingSource.ListChanged
    &lt;span style="color: blue"&gt;Dim &lt;/span&gt;count &lt;span style="color: blue"&gt;As Integer &lt;/span&gt;= &lt;span style="color: blue"&gt;Aggregate &lt;/span&gt;row &lt;span style="color: blue"&gt;In Me&lt;/span&gt;.EmailDataSet.Inbox _
                           &lt;span style="color: blue"&gt;Where &lt;/span&gt;row.Status = &lt;span style="color: #a31515"&gt;&amp;quot;Unread&amp;quot; &lt;/span&gt;_
                           &lt;span style="color: blue"&gt;Into &lt;/span&gt;UnreadCount = Count()

    &lt;span style="color: blue"&gt;Me&lt;/span&gt;.lblStatus.Text = count.ToString() &amp;amp; &lt;span style="color: #a31515"&gt;&amp;quot; unread email.&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;/p&gt;

&lt;p&gt;Now this will give us a “live” running tally and we’re not bound to the UI controls at all. Nice. For more information on Aggregate queries and DataSets &lt;a href="http://msdn.microsoft.com/en-us/vbasic/bb737877.aspx"&gt;check out this video&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;More resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb531251.aspx"&gt;Visual Basic Aggregate Clause&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/bb688088.aspx"&gt;101 Visual Basic LINQ Samples&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/bb737877.aspx"&gt;How Do I: LINQ over DataSets?&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/bb725824.aspx"&gt;How Do I: Understand Data?&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/vbasic/cc138241.aspx"&gt;How Do I: Update Related Tables?&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=9572773" 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/LINQ/default.aspx">LINQ</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Winforms/default.aspx">Winforms</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></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>Community Article: Scaling ADO.NET DataTables</title><link>http://blogs.msdn.com/bethmassi/archive/2008/12/17/community-article-scaling-ado-net-datatables.aspx</link><pubDate>Wed, 17 Dec 2008 23:43:52 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9231621</guid><dc:creator>Beth Massi</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9231621.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9231621</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9231621</wfw:comment><description>&lt;p&gt;We just released &lt;a href="http://msdn.microsoft.com/en-us/vbasic/dd364983.aspx" target="_blank"&gt;a new community article&lt;/a&gt; onto the &lt;a href="http://msdn.com/vbasic" target="_blank"&gt;Visual Basic Developer Center&lt;/a&gt; by one of our MVPs, &lt;a href="http://blog.dotnetspeech.net/" target="_blank"&gt;Jeff Certain&lt;/a&gt;, called &lt;a href="http://msdn.microsoft.com/en-us/vbasic/dd364983.aspx" target="_blank"&gt;&lt;em&gt;&lt;strong&gt;Scaling ADO.NET DataTables&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. &lt;/em&gt;In this article Jeff shows shows us how to query and aggregate data using the built in DataTable methods as well as LINQ to DataSets. He compares the performance on indexed and non indexed DataTables in a variety of scenarios. See for yourself what Jeff recommends on large sets of data.&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9231621" 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/LINQ/default.aspx">LINQ</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Community/default.aspx">Community</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></item><item><title>Editing Data from Two Tables in a Single DataGridView</title><link>http://blogs.msdn.com/bethmassi/archive/2008/10/15/editing-data-from-two-tables-in-a-single-datagridview.aspx</link><pubDate>Thu, 16 Oct 2008 04:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9001289</guid><dc:creator>Beth Massi</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/9001289.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=9001289</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=9001289</wfw:comment><description>&lt;P&gt;I've had a lot of questions lately on how to display data from two separate tables in the database into a single DataGridView for editing. It sure would be nice if all our data was in a single table, but in reality most of the time it's not. Basically the problem is that we want one single table (entity) representation on the client even though we have two physical tables in the database holding the information... thus we need to "split" the data in our entity on the client side into two or more physical tables on the server. There are many ways you can do this depending on the relations in the database and also depending on what your client-side data source happens to be. I'll present a simple, common database table scenario and then attempt to explain how we can work with it using DataTables, LINQ to SQL classes, and then an Entity Data Model --- three different approaches to working with data in Visual Studio.&lt;/P&gt;
&lt;P&gt;So let's take a very simple example. In my database I have two tables with a one-to-one relationship, Customer and CustomerContactInfo, one storing basic information about a customer and another that stores contact information:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity1_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity1_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=244 alt=entity1 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity1_thumb.jpg" width=522 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity1_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Entity Splitting DataTables&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;If we're using DataSets in our application already we probably want to represent this as a single Customer client-side DataTable. To do this, we need to specify some stored procedures in our database for Select, Insert, Update, and Delete so that when ADO.NET retrieves our data or sends back the updated, inserted and deleted rows to the database, it calls our stored procedures that do the work of splitting the data into the proper physical tables. You can easily map DataTables in the DataSet designer to stored procedures. In our example these stored procedures are going to be very simple:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;CREATE PROCEDURE &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[GetCustomers] &lt;SPAN style="COLOR: blue"&gt;AS
SELECT  &lt;/SPAN&gt;cust&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;CustomerID&lt;SPAN style="COLOR: gray"&gt;, 
        &lt;/SPAN&gt;cust&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;Title&lt;SPAN style="COLOR: gray"&gt;, 
        &lt;/SPAN&gt;cust&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;FirstName&lt;SPAN style="COLOR: gray"&gt;, 
        &lt;/SPAN&gt;cust&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;MiddleName&lt;SPAN style="COLOR: gray"&gt;, 
        &lt;/SPAN&gt;cust&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;LastName&lt;SPAN style="COLOR: gray"&gt;, 
        &lt;/SPAN&gt;cust&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;Suffix&lt;SPAN style="COLOR: gray"&gt;, 
        &lt;/SPAN&gt;cust&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;CompanyName&lt;SPAN style="COLOR: gray"&gt;, 
        &lt;/SPAN&gt;cust&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;SalesPerson&lt;SPAN style="COLOR: gray"&gt;, 
        &lt;/SPAN&gt;contact&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;EmailAddress&lt;SPAN style="COLOR: gray"&gt;, 
        &lt;/SPAN&gt;contact&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;Phone
&lt;SPAN style="COLOR: blue"&gt;FROM    &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[Customer] &lt;SPAN style="COLOR: blue"&gt;AS &lt;/SPAN&gt;cust
&lt;SPAN style="COLOR: gray"&gt;JOIN    &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[CustomerContactInfo] 
        &lt;SPAN style="COLOR: blue"&gt;AS &lt;/SPAN&gt;contact &lt;SPAN style="COLOR: blue"&gt;ON &lt;/SPAN&gt;cust&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;CustomerID &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;contact&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;CustomerID&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;CREATE PROCEDURE &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[DeleteCustomer]&lt;SPAN style="COLOR: gray"&gt;(
    &lt;/SPAN&gt;@CustomerID [int]
&lt;SPAN style="COLOR: gray"&gt;) &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;AS
BEGIN

    DELETE   &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[CustomerContactInfo]
    &lt;SPAN style="COLOR: blue"&gt;WHERE    &lt;/SPAN&gt;[CustomerID] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@CustomerID
    
    &lt;SPAN style="COLOR: blue"&gt;DELETE   &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[Customer]
    &lt;SPAN style="COLOR: blue"&gt;WHERE    &lt;/SPAN&gt;[CustomerID] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@CustomerID
    
&lt;SPAN style="COLOR: blue"&gt;END&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;SPAN style="COLOR: blue"&gt;CREATE PROCEDURE &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[UpdateCustomer]&lt;SPAN style="COLOR: gray"&gt;(
    &lt;/SPAN&gt;@CustomerID [int]&lt;SPAN style="COLOR: gray"&gt;,
    &lt;/SPAN&gt;@Title [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;8&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@FirstName [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;50&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@MiddleName [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;50&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@LastName [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;50&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@Suffix [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;10&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@CompanyName [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;128&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@SalesPerson [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;256&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@EmailAddress [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;50&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@Phone [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;25&lt;SPAN style="COLOR: gray"&gt;)
) &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;AS
BEGIN

    UPDATE  &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[Customer]
    &lt;SPAN style="COLOR: blue"&gt;SET     &lt;/SPAN&gt;[Title] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@Title&lt;SPAN style="COLOR: gray"&gt;,
            &lt;/SPAN&gt;[FirstName] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@FirstName&lt;SPAN style="COLOR: gray"&gt;,
            &lt;/SPAN&gt;[MiddleName] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@MiddleName&lt;SPAN style="COLOR: gray"&gt;,
            &lt;/SPAN&gt;[LastName] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@LastName&lt;SPAN style="COLOR: gray"&gt;,
            &lt;/SPAN&gt;[Suffix] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@Suffix&lt;SPAN style="COLOR: gray"&gt;,
            &lt;/SPAN&gt;[CompanyName] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@CompanyName&lt;SPAN style="COLOR: gray"&gt;,
            &lt;/SPAN&gt;[SalesPerson] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@SalesPerson
    &lt;SPAN style="COLOR: blue"&gt;WHERE   &lt;/SPAN&gt;[CustomerID] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@CustomerID

    &lt;SPAN style="COLOR: blue"&gt;UPDATE  &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[CustomerContactInfo]
    &lt;SPAN style="COLOR: blue"&gt;SET     &lt;/SPAN&gt;[EmailAddress] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@EmailAddress&lt;SPAN style="COLOR: gray"&gt;,
            &lt;/SPAN&gt;[Phone] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@Phone
    &lt;SPAN style="COLOR: blue"&gt;WHERE   &lt;/SPAN&gt;[CustomerID] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;@CustomerID
    
&lt;SPAN style="COLOR: blue"&gt;END&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;CREATE PROCEDURE &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[InsertCustomer]&lt;SPAN style="COLOR: gray"&gt;(
    &lt;/SPAN&gt;@Title [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;8&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@FirstName [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;50&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@MiddleName [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;50&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@LastName [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;50&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@Suffix [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;10&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@CompanyName [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;128&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@SalesPerson [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;256&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@EmailAddress [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;50&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@Phone [nvarchar]&lt;SPAN style="COLOR: gray"&gt;(&lt;/SPAN&gt;25&lt;SPAN style="COLOR: gray"&gt;),
    &lt;/SPAN&gt;@CustomerID &lt;SPAN style="COLOR: blue"&gt;int OUTPUT
&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;) &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;AS
BEGIN

    INSERT INTO &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[Customer]
    &lt;SPAN style="COLOR: blue"&gt;VALUES &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;(
        &lt;/SPAN&gt;@Title&lt;SPAN style="COLOR: gray"&gt;,
        &lt;/SPAN&gt;@FirstName&lt;SPAN style="COLOR: gray"&gt;,
        &lt;/SPAN&gt;@MiddleName&lt;SPAN style="COLOR: gray"&gt;,
        &lt;/SPAN&gt;@LastName&lt;SPAN style="COLOR: gray"&gt;,
        &lt;/SPAN&gt;@Suffix&lt;SPAN style="COLOR: gray"&gt;,
        &lt;/SPAN&gt;@CompanyName&lt;SPAN style="COLOR: gray"&gt;,
        &lt;/SPAN&gt;@SalesPerson &lt;SPAN style="COLOR: gray"&gt;)
    
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;-- Get back the customer ID 
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;SELECT &lt;/SPAN&gt;@customerID &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;CustomerID
    &lt;SPAN style="COLOR: blue"&gt;FROM &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[Customer]
    &lt;SPAN style="COLOR: blue"&gt;WHERE &lt;/SPAN&gt;&lt;SPAN style="COLOR: magenta"&gt;@@ROWCOUNT &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;&amp;gt; &lt;/SPAN&gt;0 &lt;SPAN style="COLOR: gray"&gt;AND &lt;/SPAN&gt;[CustomerID] &lt;SPAN style="COLOR: gray"&gt;= &lt;/SPAN&gt;&lt;SPAN style="COLOR: magenta"&gt;scope_identity&lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;()

    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;INSERT INTO &lt;/SPAN&gt;[dbo]&lt;SPAN style="COLOR: gray"&gt;.&lt;/SPAN&gt;[CustomerContactInfo]
    &lt;SPAN style="COLOR: blue"&gt;VALUES &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;(
        &lt;/SPAN&gt;@customerID&lt;SPAN style="COLOR: gray"&gt;,
        &lt;/SPAN&gt;@EmailAddress&lt;SPAN style="COLOR: gray"&gt;,
        &lt;/SPAN&gt;@Phone&lt;SPAN style="COLOR: gray"&gt;)
    
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;END&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 that we have that set up, open up the Data Source Window in Visual Studio and add a new data source, select the Database and then select just the GetCustomers stored procedure:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity2_4.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity2_4.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=480 alt=entity2 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity2_thumb_1.jpg" width=625 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity2_thumb_1.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Click Finish and then open up the DataSet designer by double-clicking on the CustomerDataset.xsd in the Solution Explorer. You'll notice that the name of the DataTable is GetCustomers so change that to just "Customer". Next we need to configure the DataTable so that it will use our stored procedures so right click on the DataTable and select "Configure...". The TableAdapter Configuration Wizard should open and this will allow you to map your stored procedures to the Update, Insert and Delete commands. By default the fields will match up by name so you shouldn't have to do anything but drop down the combo boxes and select the right procedures for each action.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity3_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity3_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=480 alt=entity3 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity3_thumb.jpg" width=624 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity3_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;To test this out you can drag the Customer table from the Data Sources window on to a Windows Form as a DataGrid and immediately run it. &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity4_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity4_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=378 alt=entity4 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity4_thumb.jpg" width=640 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity4_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;You will see the data from both tables displayed in the grid and they will be editable. As you update, insert and delete rows here, the DataSet will keep track of these changes for you. So when it is time to save the data via a call to the TableAdapterManager.UpdateAll method, the proper stored procedure will be called for each row that was modified. &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity5_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity5_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=189 alt=entity5 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity5_thumb.jpg" width=640 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity5_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Entity Splitting LINQ to SQL Classes&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;So with a Dataset, the DataTables do not have to map one-to-one with your database tables, but you need to specify how the data should be saved back to the database via stored procedures. This is also true if using LINQ to SQL classes. In that case though, you drag methods onto the method pane &lt;STRONG&gt;first&lt;/STRONG&gt; and then map them to the class in the designer by right-clicking on the class and selecting "Configure Behavior...". &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity6_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity6_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=480 alt=entity6 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity6_thumb.jpg" width=639 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity6_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;However with LINQ to SQL classes you can't map the Select behavior unfortunately. What you do instead is map the result of the GetCustomers method to a result type of Customer (the class we created on the design surface). &lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity7_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity7_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN: 5px 10px 0px 0px; BORDER-RIGHT-WIDTH: 0px" height=182 alt=entity7 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity7_thumb.jpg" width=240 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity7_thumb.jpg"&gt;&lt;/A&gt;Then when accessing the customers data you need to remember to call the GetCustomers method and not access the Customers directly in the DataContext, otherwise you'll get a SQLException that it cant find the additional columns when retrieving the data (in our case EmailAddress and Phone). &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;db &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;MyDataContext

&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&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&lt;SPAN style="COLOR: green"&gt;    'This will properly populate a collection of our&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;    ' Customer entities.&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Me&lt;/SPAN&gt;.CustomerBindingSource.DataSource = db.GetCustomers
&lt;SPAN style="COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;To save the data in a connected state like this we can simply call SubmitChanges on the DataContext. The LINQ to SQL DataContext tracks the state of each modification, deletion or insertion into the collection of Customers and will call the corresponding stored procedures that we configured.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Private Sub &lt;/SPAN&gt;CustomerBindingNavigatorSaveItem_Click() _
   &lt;SPAN style="COLOR: blue"&gt;Handles &lt;/SPAN&gt;CustomerBindingNavigatorSaveItem.Click
   &lt;SPAN style="COLOR: blue"&gt;Try
       &lt;/SPAN&gt;db.SubmitChanges()

       MsgBox(&lt;SPAN style="COLOR: #a31515"&gt;"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;(Note: In order to get get drag-drop data binding in Windows Forms to work with LINQ to SQL objects you need to select Data --&amp;gt; "Add New Data Source" on the main menu, then select Object (not database). Then select the Customer object and Finish. This will populate your Data Sources window so you can drag the grid onto a Windows form.)&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Entity Splitting Using the Entity Data Model&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This scenario becomes pretty straight-forward and automatic using the &lt;A href="http://msdn.microsoft.com/en-us/library/bb399183.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb399183.aspx"&gt;Entity Framework (EF)&lt;/A&gt; and you're not required to write any stored procedures to get it to work. This is because EF provides more complex mappings out of the box than LINQ to SQL or DataSets. And EF separates your database schema from your object model by providing a mapping layer. If you have &lt;A href="http://msdn.microsoft.com/en-us/vstudio/products/cc533448.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/vstudio/products/cc533448.aspx"&gt;Visual Studio 2008 Service Pack 1&lt;/A&gt; you can create what's called an Entity Data Model which provides an ObjectContext, similar in theory to the LINQ to SQL DataContext above, but it provides many &lt;A href="http://msdn.microsoft.com/en-us/library/cc716779.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/cc716779.aspx"&gt;more mapping features&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;When you add a new Entity Data Model to your project you can choose to generate it from the database or you can create an empty model. For this example I'll choose to generate it from the database and I'll select just the Customer and CustomerContactInfo tables and no stored procedures this time. (Note that I can still map stored procs to the update, insert and delete behaviors if I need to though.)&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity8_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity8_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=289 alt=entity8 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity8_thumb.jpg" width=479 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity8_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;This looks just like our database model except you can see the navigation properties displayed that let us navigate from one entity to related ones. Notice the association is also shown as one-to-(none or)one. To set up the mapping so that it will automatically split the entity for us first we need to adjust the Customer by adding the EmailAddress and Phone. You can select the EmailAddress and Phone properties of the CustomerContactInfo and cut then paste them into the Customer. Then you can delete the CustomerContactInfo class from the design surface. &lt;/P&gt;
&lt;P&gt;Now select the Customer and look at the Mapping Details window. Below the column mappings you will see &amp;lt;Add a Table or View&amp;gt;. Drop that down and select CustomerContactInfo and it will automatically map the columns in that table to the properties that we added.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity9_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity9_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=359 alt=entity9 src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity9_thumb.jpg" width=640 border=0 mce_src="http://blogs.msdn.com/blogfiles/bethmassi/WindowsLiveWriter/EditingDatafromTwoTablesinaSingleDataGri_D9C4/entity9_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Save the model and rebuild the project. Now you can add Customer as a data source for drag-drop Winforms data binding the same way you do for LINQ to SQL classes or your own objects. And the code for loading and saving of the Customers is similar to the LINQ to SQL code above except loading the Customers is much more intuitive. And the ObjectContext tracks changes for you and generates the proper insert, update, and delete statements automatically without you having to define stored procedures to do the splitting. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Private &lt;/SPAN&gt;db &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;MyDatabaseEntities

&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: blue"&gt;Me&lt;/SPAN&gt;.CustomerBindingSource.DataSource = db.Customer
&lt;SPAN style="COLOR: blue"&gt;End Sub

Private Sub &lt;/SPAN&gt;CustomerBindingNavigatorSaveItem_Click() _
    &lt;SPAN style="COLOR: blue"&gt;Handles &lt;/SPAN&gt;CustomerBindingNavigatorSaveItem.Click

    &lt;SPAN style="COLOR: blue"&gt;Try
        &lt;/SPAN&gt;db.SaveChanges()

        MsgBox(&lt;SPAN style="COLOR: #a31515"&gt;"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;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;This is just the tip of the iceberg using the Entity Data Model. I'd recommend reading the &lt;A href="http://msdn.microsoft.com/en-us/library/bb399572.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb399572.aspx"&gt;documentation in the MSDN library&lt;/A&gt;, visiting the &lt;A href="http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=533&amp;amp;SiteID=1" target=_blank mce_href="http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=533&amp;amp;SiteID=1"&gt;forums&lt;/A&gt; and the &lt;A href="http://blogs.msdn.com/dsimmons/pages/entity-framework-faq.aspx" target=_blank mce_href="http://blogs.msdn.com/dsimmons/pages/entity-framework-faq.aspx"&gt;FAQ&lt;/A&gt;, as well as visiting &lt;A href="http://learnentityframework.com/events" target=_blank mce_href="http://learnentityframework.com/events"&gt;Julie Lerman's site&lt;/A&gt; (she's been living EF since the early Betas). I'm just learning EF myself but as you can see it allows you to model more complex data scenarios. &lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9001289" 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/LINQ/default.aspx">LINQ</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Winforms/default.aspx">Winforms</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></item><item><title>MSDN Magazine - Dynamic Data Entry With XML Literals</title><link>http://blogs.msdn.com/bethmassi/archive/2008/10/01/msdn-magazine-dynamic-data-entry-with-xml-literals.aspx</link><pubDate>Thu, 02 Oct 2008 04:49:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8972596</guid><dc:creator>Beth Massi</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/8972596.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=8972596</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=8972596</wfw:comment><description>&lt;p&gt;Check out the latest news on the &lt;a href="http://msdn.microsoft.com/en-us/vbasic/default.aspx" target="_blank"&gt;VB Dev Center&lt;/a&gt;. I'm finally headlining myself ;-) &lt;/p&gt;  &lt;p&gt;I'm in the &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc947916.aspx" target="_blank"&gt;October issue of MSDN Magazine&lt;/a&gt;. I've been managing the content for the Basic Instincts column for a little over a year now where we rotate writers from the VB Team. This month is my birthday month so I decided to take this one on personally. :-)&lt;/p&gt;  &lt;p&gt;Enjoy! &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8972596" 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/Community/default.aspx">Community</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/Data/default.aspx">Data</category></item><item><title>Accessing Open XML Document Parts with the Open XML SDK</title><link>http://blogs.msdn.com/bethmassi/archive/2008/07/30/accessing-openxml-document-parts-with-the-openxml-sdk.aspx</link><pubDate>Thu, 31 Jul 2008 05:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8792823</guid><dc:creator>Beth Massi</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/8792823.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=8792823</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=8792823</wfw:comment><description>&lt;P&gt;About a month ago the &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=AD0B72FB-4A1D-4C52-BDB5-7DD7E816D046&amp;amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyID=AD0B72FB-4A1D-4C52-BDB5-7DD7E816D046&amp;amp;displaylang=en"&gt;Open XML SDK 1.0 (June 08 update) was released&lt;/A&gt;. The SDK provides strongly typed document part access to Word 2007, Excel 2007 and PowerPoint 2007 documents. The SDK has been a CTP for a while, but last month version 1.0 was finally released. So I installed this baby last week and started playing around with it and found it really easy to use after briefly looking at &lt;A href="http://msdn.microsoft.com/en-us/library/bb448854.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb448854.aspx"&gt;the documentation&lt;/A&gt;. The &lt;A href="http://msdn.microsoft.com/en-us/library/bb491088.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/bb491088.aspx"&gt;How Do I section&lt;/A&gt; is a great place to start.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Upgrading the Letter Generator&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;I decided to upgrade my &lt;A href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx"&gt;Word 2007 letter generator program&lt;/A&gt; to use the SDK to manipulate the packages. Remember that Office 2007 documents are really just archive files, so if you rename them to .ZIP you can take a look at the contents of the package. The Open XML Package spec defines a set of XML files that contain the content and define the relationships for all of the document parts stored in a single package. To programmatically manipulate them you can use the raw System.IO.Packaging namespace, but the SDK's DocumentFormat.OpenXml.Packaging namespace is much easier to work with.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;My &lt;A href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2007/12/06/mail-merging-with-word-and-linq-to-xml-in-vb.aspx"&gt;mail merge program&lt;/A&gt; uses XML literals to construct XML for the document part of a Word 2007 file based on data in the Northwind database. The LINQ query was a piece of cake compared to figuring out how to manipulate the .docx package in order to replace the document.xml (called the MainDocument) part. Not that the final code is particularly long, it was just a pain to figure it out. The SDK not only saved me a few lines of code, it made the code much more readable and took only a few minutes to write. (I updated the code for the &lt;A href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=whatsnewvb&amp;amp;DownloadId=336" target=_blank mce_href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=whatsnewvb&amp;amp;DownloadId=336"&gt;WordMailMerge program on Code Gallery&lt;/A&gt;).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Getting Started with the Open XML SDK&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Let's take another simple example that constructs a MainDocument part using XML literals and then replaces it in a .docx package using the SDK. This time I'll focus on the code that manipulates the Open XML package with the SDK not on the particulars of XML Literals. The first thing I recommend is to install the &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=46B6BF86-E35D-4870-B214-4D7B72B02BF9&amp;amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyId=46B6BF86-E35D-4870-B214-4D7B72B02BF9&amp;amp;displaylang=en"&gt;VSTO Power Tools&lt;/A&gt; so you can open Office 2007 documents and manipulate the parts directly in the Visual Studio IDE &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 mce_href="http://blogs.msdn.com/bethmassi/archive/2008/07/29/handy-visual-studio-add-in-to-view-office-2007-files.aspx"&gt;like I showed in my last post&lt;/A&gt; using the Open XML Package Editor. &lt;/P&gt;
&lt;P&gt;Of course you'll need to also &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=AD0B72FB-4A1D-4C52-BDB5-7DD7E816D046&amp;amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyID=AD0B72FB-4A1D-4C52-BDB5-7DD7E816D046&amp;amp;displaylang=en"&gt;install the SDK&lt;/A&gt; which places the DocumentFormat.OpenXML.dll assembly into your GAC. Add a reference to this assembly in your project. As an aside, when x-copy deploying to a machine with the .NET Framework on it already just make sure you deploy the DocumentFormat.OpenXML.dll assembly alongside your application to avoid having to install the SDK on the target machine. The easiest thing to do is select "Show All Files" in the Solution Explorer, expand the References, and on the Properties for the DocumentFormat.OpenXML reference set "Copy Local" = True. This will place a private copy of the assembly next to your application when it's built. &lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/bethmassi/images/8792597/228x375.aspx" mce_src="http://blogs.msdn.com/photos/bethmassi/images/8792597/228x375.aspx"&gt; &lt;/P&gt;
&lt;P&gt;Now create a new Word 2007 document with some simple text in it, for instance, type: "This is my document" then save it and add the .docx file to your Visual Basic project. Double-click on it and that opens the Open XML Package Editor:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/bethmassi/images/8792532/original.aspx" mce_src="http://blogs.msdn.com/photos/bethmassi/images/8792532/original.aspx"&gt; &lt;/P&gt;
&lt;P&gt;We can manipulate the parts through this editor if we want to but what I really want to do is replace the document.xml with our own we create using XML literals and embedded expressions. Double-click on the document.xml to open the MainDocument part in the XML Editor (if the XML editor opens and the XML is all on one line with no breaks then just select all the contents and cut then paste it back into the editor and it will put the proper line breaks in there for you : Ctrl + A,X,V). &lt;/P&gt;
&lt;P&gt;For this simple example, let's place the executing user's name into the document. C&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;reate the XML Literal and an embedded expression by pasting the document.xml into the VB Editor and adding an expression to print out the executing user's name:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;myDoc = &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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;1.0&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;utf-8&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;yes&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;?&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:document &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xmlns:ve&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;http://schemas.openxmlformats.org/markup-compatibility/2006&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xmlns:o&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;urn:schemas-microsoft-com:office:office&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xmlns:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;http://schemas.openxmlformats.org/officeDocument/2006/relationships&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xmlns:m&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;http://schemas.openxmlformats.org/officeDocument/2006/math&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xmlns:v&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;urn:schemas-microsoft-com:vml&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xmlns:wp&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xmlns:w10&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;urn:schemas-microsoft-com:office:word&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xmlns:w&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;http://schemas.openxmlformats.org/wordprocessingml/2006/main&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;xmlns:wne&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;http://schemas.microsoft.com/office/word/2006/wordml&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
               &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:body&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                   &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:p &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00DD17EB&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidRDefault&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00361264&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                       &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                           &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;This is &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;&amp;lt;%=&lt;/SPAN&gt; Environment.UserName &lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;'s document&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:t&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                       &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:r&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                   &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:p&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                   &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:sectPr &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidR&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00DD17EB&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:rsidSect&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;00DD17EB&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
                       &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:pgSz &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:w&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;12240&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:h&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;15840&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
                       &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:pgMar &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:top&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;1440&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:right&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;1440&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:bottom&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;1440&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"
                           &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:left&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;1440&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:header&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;720&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:footer&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;720&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:gutter&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;0&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
                       &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:cols &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:space&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;720&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
                       &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:docGrid &lt;/SPAN&gt;&lt;SPAN style="COLOR: #b96464"&gt;w:linePitch&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;360&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;/&amp;gt;
                   &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:sectPr&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
               &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:body&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;
           &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;w:document&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;STRONG&gt;Replacing the MainDocument Part&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Before the SDK, replacing the MainDocument part in the package we had to figure out the right content type and write the code that deleted then added the new part. We also needed to add a reference to WindowsBase (a 3.0 assembly) in order to access the System.IO.Packaging namespace.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.IO.Packaging
&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.IO&lt;/PRE&gt;&lt;PRE class=code&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;SPAN style="COLOR: green"&gt;&lt;STRONG&gt;'**** Without OpenXML SDK&lt;/STRONG&gt;
&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;"/word/document.xml"&lt;/SPAN&gt;, UriKind.Relative)
&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;contentType = &lt;SPAN style="COLOR: #a31515"&gt;"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;docFile = CurDir() &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"\MyDocument.docx"

&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;p &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;Package = Package.Open(docFile)
    &lt;SPAN style="COLOR: green"&gt;'Delete the current document.xml file
    &lt;/SPAN&gt;p.DeletePart(uri)

    &lt;SPAN style="COLOR: green"&gt;'Replace that part with our XDocument
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;replace &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;PackagePart = p.CreatePart(uri, contentType)
    &lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;sw &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;StreamWriter(replace.GetStream())
        myDoc.Document.Save(sw)
     &lt;SPAN style="COLOR: blue"&gt;End Using
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;End Using&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;For this example it's pretty easy, however if you add/remove parts it's up to you to update the relations in the package and this isn't an easy task using this raw API. Enter the Open XML SDK. Now we don't need to add a reference to WindowsBase, only to DocumentFormat.OpenXML and import the Packaging namespace contained within. Then our code can access the parts of the document in a strongly-typed way:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;DocumentFormat.OpenXml.Packaging&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;Imports &lt;/SPAN&gt;System.IO&lt;/PRE&gt;&lt;PRE class=code&gt;...&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;&lt;STRONG&gt;'***** Use the OpenXML SDK for easier access to parts&lt;/STRONG&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;docFile = CurDir() &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"\MyDocument.docx"

&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;wordDoc = WordprocessingDocument.Open(docFile, &lt;SPAN style="COLOR: blue"&gt;True&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;wordDoc
&lt;SPAN style="COLOR: green"&gt;    'Replace the document part with our XML
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;sw &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create))
        myDoc.Document.Save(sw)
&lt;SPAN style="COLOR: blue"&gt;    End Using
End Using&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;FONT face=Arial&gt;After we run this code you'll see that the MainDocument part now has the user name in the document body as described by our XML literal. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Using LINQ with the Open XML SDK&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;Using the SDK we can &lt;/FONT&gt;&lt;FONT face=Arial&gt;also write LINQ queries over the part collections. For instance if we want to select all the top level parts and any of their sub-parts, we can write a query like so:&lt;/FONT&gt;&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;wordDoc&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;  Dim &lt;/SPAN&gt;parts = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;part &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;wordDoc.Parts _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;Select &lt;/SPAN&gt;part.OpenXmlPart, _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; part.RelationshipId, _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; part.OpenXmlPart.RelationshipType, _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SubParts = _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;subPart &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;part.OpenXmlPart.Parts _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;Select &lt;/SPAN&gt;subPart.OpenXmlPart, _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; subPart.RelationshipId, _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; subPart.OpenXmlPart.RelationshipType _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).ToList&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;End Using&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;This query returns similar information to what you get with the Open XML Package Editor if we look at the same document. If we display the query results in two related DataGridViews we'll see that the MainDocument part contains additional parts for things like themes, styles and settings. &lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/bethmassi/images/8792715/640x227.aspx" mce_src="http://blogs.msdn.com/photos/bethmassi/images/8792715/640x227.aspx"&gt; &lt;/P&gt;
&lt;P&gt;If we want to access the actual XML content for each of the OpenXmlParts we can call the GetStream method on the OpenXmlPart we want and pass it a StreamReader which we can use to load an XDocument object.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;wordDoc

 &lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;parts = &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;part &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;wordDoc.Parts _
             &lt;SPAN style="COLOR: blue"&gt;Select &lt;/SPAN&gt;Doc = XDocument.Load(&lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;StreamReader(part.OpenXmlPart.GetStream())), _
                    part.OpenXmlPart, _
                    part.RelationshipId, _
                    part.OpenXmlPart.RelationshipType, _
                    SubParts = _
                    ( _
                     &lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;subPart &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;part.OpenXmlPart.Parts _
                     &lt;SPAN style="COLOR: blue"&gt;Select &lt;/SPAN&gt;Doc = XDocument.Load(&lt;SPAN style="COLOR: blue"&gt;New &lt;/SPAN&gt;StreamReader(subPart.OpenXmlPart.GetStream())), _
                            subPart.OpenXmlPart, _
                            subPart.RelationshipId, _
                            subPart.OpenXmlPart.RelationshipType _
                    ).ToList
&lt;SPAN style="COLOR: blue"&gt;End Using&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;STRONG&gt;Loading and Querying the XDocument from the Package&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Let's say we have a case where we can't use XML Literals and embedded expressions, instead we want to pull out the MainDocument part and find and replace text inside. We can do this using XML Axis properties. This can get pretty tricky because there may be a lot of formatting information in the document. An easier way may be to use content controls which you can alias so that it's easier to query those instead, but for this example it's a pretty simple query to find our body text and replace the word "my" with the user name. &lt;/P&gt;&lt;PRE class=code&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:w&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;http://schemas.openxmlformats.org/wordprocessingml/2006/main&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&lt;FONT color=#000000&gt;...&lt;/FONT&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;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;docFile = CurDir() &amp;amp; &lt;SPAN style="COLOR: #a31515"&gt;"\MyDocument.docx"
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;wordDoc = WordprocessingDocument.Open(docFile, &lt;SPAN style="COLOR: blue"&gt;True&lt;/SPAN&gt;)
&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;myDoc &lt;SPAN style="COLOR: blue"&gt;As &lt;/SPAN&gt;XDocument

&lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;wordDoc
    &lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;xr &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;StreamReader(wordDoc.MainDocumentPart.GetStream())
        &lt;SPAN style="COLOR: green"&gt;'Load the MainDocument part's XML
        &lt;/SPAN&gt;myDoc = XDocument.Load(xr)
    &lt;SPAN style="COLOR: blue"&gt;End Using

    &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;'Find the only line of text in this document
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;Dim &lt;/SPAN&gt;element = (&lt;SPAN style="COLOR: blue"&gt;From &lt;/SPAN&gt;item &lt;SPAN style="COLOR: blue"&gt;In &lt;/SPAN&gt;myDoc...&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;&lt;/SPAN&gt;w:t&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;)(0)

    &lt;SPAN style="COLOR: green"&gt;'Replace the value of the element
    &lt;/SPAN&gt;element.Value = &lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;s&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;This is &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;&amp;lt;%=&lt;/SPAN&gt; Environment.UserName &lt;SPAN style="BACKGROUND: #fffebf; COLOR: #555555"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #555555"&gt;'s document&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #844646"&gt;s&lt;/SPAN&gt;&lt;SPAN style="COLOR: #6464b9"&gt;&amp;gt;&lt;/SPAN&gt;.Value

    &lt;SPAN style="COLOR: blue"&gt;Using &lt;/SPAN&gt;sw &lt;SPAN style="COLOR: blue"&gt;As New &lt;/SPAN&gt;StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create))
        &lt;SPAN style="COLOR: green"&gt;'Save the modified XML back to the MainDocument part
        &lt;/SPAN&gt;myDoc.Save(sw)
    &lt;SPAN style="COLOR: blue"&gt;End Using

End Using&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;One of the cool things about using the Open XML SDK is that you don't have to have Office installed to run any of this code. So it's a great alternative instead of using slow COM automation to manipulate documents.&lt;/P&gt;
&lt;P&gt;As I explore Open XML in Office 2007 more and more I'll post more realistic business examples using LINQ to XML and Visual Basic. For now, you may want to sink your teeth into Ken Getz's Advanced Basics March 2008 article in MSDN Magazine: &lt;A href="http://msdn.microsoft.com/en-us/magazine/cc337894.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/magazine/cc337894.aspx"&gt;&lt;EM&gt;Office 2007 Files and LINQ&lt;/EM&gt;&lt;/A&gt;&lt;EM&gt;. &lt;/EM&gt;This article also shows off some important XML namespace features of Visual Basic.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8792823" 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/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/XML/default.aspx">XML</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/Office/default.aspx">Office</category></item><item><title>Article: Sharpening Your Axis with Visual Basic 9</title><link>http://blogs.msdn.com/bethmassi/archive/2008/06/30/article-sharpening-your-axis-with-visual-basic-9.aspx</link><pubDate>Tue, 01 Jul 2008 00:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8673244</guid><dc:creator>Beth Massi</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/8673244.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=8673244</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=8673244</wfw:comment><description>&lt;P&gt;In the July/August issue of &lt;A class="" href="http://www.code-magazine.com/" mce_href="http://www.code-magazine.com/"&gt;CoDe Magazine&lt;/A&gt; there's an article I wrote with Avner Aharoni&amp;nbsp;(the Program Manager on XML literals) called &lt;EM&gt;&lt;A class="" href="http://www.code-magazine.com/article.aspx?quickid=0807061" target=_blank mce_href="http://www.code-magazine.com/article.aspx?quickid=0807061"&gt;&lt;STRONG&gt;Sharpening Your Axis with Visual Basic 9&lt;/STRONG&gt;&lt;/A&gt;.&lt;/EM&gt; (They just opened up online access to even non-subscribers today!) I highly recommend this article which shows you from the beginning how XML literals, embedded expressions and axis properties work in Visual Basic. &lt;/P&gt;
&lt;P&gt;I start with the basic syntax and definitions&amp;nbsp;and then walk through the &lt;A class="" href="http://msdn.microsoft.com/en-us/vbasic/bb840042.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/vbasic/bb840042.aspx"&gt;XML to Schema tool &lt;/A&gt;(which has been added to VS2008 SP1) to enable XML IntelliSense, as well as show some practical examples of using these features with LINQ. Avner describes how IntelliSense works and discusses advanced scenarios with XML namespaces. We end with tips-and-tricks which get you thinking about using XML literals in other text generation/manipulation scenarios. &lt;/P&gt;
&lt;P&gt;If you like this topic, so do I! Check out the &lt;A class="" href="http://blogs.msdn.com/bethmassi/archive/tags/XML/default.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/tags/XML/default.aspx"&gt;XML topic&amp;nbsp;feed from this blog&lt;/A&gt; for more resources.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8673244" 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/LINQ/default.aspx">LINQ</category><category domain="http://blogs.msdn.com/bethmassi/archive/tags/VS2008/default.aspx">VS2008</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></item><item><title>Dynamic Data Entry with WPF and LINQ</title><link>http://blogs.msdn.com/bethmassi/archive/2008/06/24/dynamic-data-entry-with-wpf-and-linq.aspx</link><pubDate>Wed, 25 Jun 2008 01:29:22 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8649441</guid><dc:creator>Beth Massi</dc:creator><slash:comments>22</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/8649441.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=8649441</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=8649441</wfw:comment><description>&lt;p&gt;In &lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/06/12/dynamic-ui-with-wpf-and-linq.aspx" target="_blank"&gt;my last post on this subject&lt;/a&gt; I explored creating WPF UI's dynamically using XML literals. The one part that bugged me a bit was that even though the UI was dynamic, we were using a fixed object model of our customer (using LINQ to SQL classes). I wanted to augment this code a bit more so that we could not only dynamically generate the WPF UI but also dynamically edit &lt;strong&gt;any &lt;/strong&gt;maintenance table in our database -- not just customer. What I really wanted to enable is if we modify the database schema of any of our maintenance tables then we don't have to update our object model and recompile our code. &lt;/p&gt; &lt;p&gt;To achieve this I decided to explore loading and editing a simple untyped DataTable at runtime. This worked well using XML literals again -- this time to generate the SELECT and UPDATE statements for the SqlDataAdapter. One thing to note, this technique relies on the database to enforce any validation rules. This is why I would only use this type of dynamic form to edit very simple tables (aka. maintenance tables).&lt;/p&gt; &lt;p&gt;For this example I decided to create a typed DataTable for my TableSchema instead as well, eliminating the need for LINQ to SQL classes in the project. If you recall this is used to hold the column metadata (ColumnName, DataType, etc.) for the table we want to edit. I just right-clicked on my project to add a new item and selected DataSet. I named it TableSchemaDataSet and then just simply dragged the GetTableSchema stored procedure (which we added to 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; in the &lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/06/12/dynamic-ui-with-wpf-and-linq.aspx" target="_blank"&gt;last post&lt;/a&gt;) onto the design surface. This automatically creates a typed DataTable for us with no fuss. I renamed the DataTable to TableSchema and saved it. &lt;/p&gt; &lt;p&gt;&lt;img src="http://blogs.msdn.com/photos/bethmassi/images/8649019/original.aspx"&gt; &lt;/p&gt; &lt;p&gt;Now for the fun part. We need to load an untyped DataTable into our dynamically generated WPF form because we don't want to make any assumptions about the schema of the table we're editing (except that there is a primary key of some sort). DataTables and DataSets work well with WPF but there are a couple things we need to set up manually since we're loading this all at runtime. (Writing the code to load and save the DataTable makes me REALLY appreciate the DataSet designer and the code that it generates for you). &lt;/p&gt; &lt;p&gt;First I set up a Public property on the form to hold the name of the table we want to edit called TableName and set the default to "Shippers" this time. Then I created some private class level variables to reference the ADO.NET objects we'll need. (Take a look at the &lt;a href="http://blogs.msdn.com/bethmassi/archive/2008/06/12/dynamic-ui-with-wpf-and-linq.aspx" target="_blank"&gt;last post&lt;/a&gt; for the XAML markup of the Window, it's exactly the same for this example.)&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;Imports&lt;/span&gt; &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(185,100,100)"&gt;xmlns&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;Imports&lt;/span&gt; &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(185,100,100)"&gt;xmlns:x&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;Imports&lt;/span&gt; System.Windows.Markup
&lt;span style="color: rgb(0,0,255)"&gt;Imports&lt;/span&gt; System.Data.SqlClient
&lt;span style="color: rgb(0,0,255)"&gt;Imports&lt;/span&gt; System.Data

&lt;span style="color: rgb(0,0,255)"&gt;Partial&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Class&lt;/span&gt; Window2
    &lt;span style="color: rgb(0,128,0)"&gt;'This is the metadata table we created in the DataSet Designer
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; TableSchema &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; TableSchemaDataSet.TableSchemaDataTable
    &lt;span style="color: rgb(0,128,0)"&gt;'ADO.NET objects used to load and save the table we're editing
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; TableDataAdapter &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; SqlDataAdapter
    &lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; TableConnection &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; SqlConnection(&lt;span style="color: rgb(0,0,255)"&gt;My&lt;/span&gt;.Settings.NorthwindConnectionString)
    &lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; Table &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; DataTable
    &lt;span style="color: rgb(0,128,0)"&gt;'This is the key field used in searching for a row in this example
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; PKField &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; TableSchemaDataSet.TableSchemaRow

    &lt;span style="color: rgb(0,128,0)"&gt;'This property can be set before the Form.Show() to edit any table
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; m_tableName &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;String&lt;/span&gt; = &lt;span style="color: rgb(163,21,21)"&gt;"Shippers"
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Property&lt;/span&gt; TableName() &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;String
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;Get
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;Return&lt;/span&gt; m_tableName
        &lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Get
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;Set&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;ByVal&lt;/span&gt; value &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;String&lt;/span&gt;)
            m_tableName = value
        &lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Set
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Property&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;In the Loaded event handler we can now load the metadata, create and load our XAML to display our UI just like before, and then set our UpdateCommand on the TableDataAdapter. &lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub&lt;/span&gt; Window1_Loaded() &lt;span style="color: rgb(0,0,255)"&gt;Handles&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;MyBase&lt;/span&gt;.Loaded
    &lt;span style="color: rgb(0,0,255)"&gt;Try
&lt;/span&gt;        &lt;span style="color: rgb(0,128,0)"&gt;'Get the schema of the database table we want to edit
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;Dim&lt;/span&gt; taSchema &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; TableSchemaDataSetTableAdapters.TableSchemaTableAdapter
        taSchema.Fill(&lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableSchema, &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableName)

        &lt;span style="color: rgb(0,128,0)"&gt;'Create the DataTable that will hold the record we're editing
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.Table = &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; DataTable(&lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableName)&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;        Me&lt;/span&gt;.Title = &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableName
        &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.LoadUI() &lt;br&gt;        &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.SetPrimaryKey()
        &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.SetUpdateCommand()        &lt;br&gt;
    &lt;span style="color: rgb(0,0,255)"&gt;Catch&lt;/span&gt; ex &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; Exception
        MsgBox(ex.ToString)
        &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.Close()
    &lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Try
&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub

&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub&lt;/span&gt; LoadUI()

    &lt;span style="color: rgb(0,0,255)"&gt;Dim&lt;/span&gt; UI = &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;Grid&lt;/span&gt; &lt;span style="color: rgb(185,100,100)"&gt;xmlns:x&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;"&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"
&lt;/a&gt;&lt;/span&gt;                 &lt;span style="color: rgb(185,100,100)"&gt;xmlns&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;"&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"
&lt;/a&gt;&lt;/span&gt;                 &lt;span style="color: rgb(185,100,100)"&gt;Name&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;Grid1&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                 &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                     &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color: rgb(185,100,100)"&gt;Width&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;100*&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;/&amp;gt;
&lt;/span&gt;                     &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;ColumnDefinition&lt;/span&gt; &lt;span style="color: rgb(185,100,100)"&gt;Width&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;200*&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;/&amp;gt;
&lt;/span&gt;                 &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;Grid.ColumnDefinitions&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                 &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;StackPanel&lt;/span&gt; &lt;span style="color: rgb(185,100,100)"&gt;Name&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;StackLabels&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt; &lt;span style="color: rgb(185,100,100)"&gt;Margin&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;3&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                     &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;From&lt;/span&gt; column &lt;span style="color: rgb(0,0,255)"&gt;In&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableSchema _
                         &lt;span style="color: rgb(0,0,255)"&gt;Where&lt;/span&gt; column.IsPrimaryKey = 0 &lt;span style="color: rgb(0,0,255)"&gt;AndAlso&lt;/span&gt; column.DataType &amp;lt;&amp;gt; &lt;span style="color: rgb(163,21,21)"&gt;"timestamp"&lt;/span&gt; _
                         &lt;span style="color: rgb(0,0,255)"&gt;Select&lt;/span&gt; &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;Label
&lt;/span&gt;                                    &lt;span style="color: rgb(185,100,100)"&gt;Height&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;28&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"
&lt;/span&gt;                                    &lt;span style="color: rgb(185,100,100)"&gt;Name&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; column.ColumnName &amp;amp; &lt;span style="color: rgb(163,21,21)"&gt;"Label"&lt;/span&gt; &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                                    &lt;span style="color: rgb(185,100,100)"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;Right&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                                    &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; column.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;:&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;Label&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                 &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;StackPanel&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                 &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;StackPanel&lt;/span&gt; &lt;span style="color: rgb(185,100,100)"&gt;Grid.Column&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;1&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt; &lt;span style="color: rgb(185,100,100)"&gt;Name&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;StackFields&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt; &lt;span style="color: rgb(185,100,100)"&gt;Margin&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;3&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                     &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;From&lt;/span&gt; column &lt;span style="color: rgb(0,0,255)"&gt;In&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableSchema _
                         &lt;span style="color: rgb(0,0,255)"&gt;Where&lt;/span&gt; column.IsPrimaryKey = 0 &lt;span style="color: rgb(0,0,255)"&gt;AndAlso&lt;/span&gt; column.DataType &amp;lt;&amp;gt; &lt;span style="color: rgb(163,21,21)"&gt;"timestamp"&lt;/span&gt; _
                         &lt;span style="color: rgb(0,0,255)"&gt;Select&lt;/span&gt; GetUIElement(column) &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                 &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;StackPanel&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;             &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;Grid&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;&lt;br&gt;
&lt;/span&gt;     &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.DynamicContent.Content = XamlReader.Load(UI.CreateReader())

&lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub

&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Function&lt;/span&gt; GetUIElement(&lt;span style="color: rgb(0,0,255)"&gt;ByVal&lt;/span&gt; columnInfo &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; TableSchemaDataSet.TableSchemaRow) &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; XElement
    &lt;span style="color: rgb(0,0,255)"&gt;Select&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Case&lt;/span&gt; columnInfo.DataType.ToLower
        &lt;span style="color: rgb(0,0,255)"&gt;Case&lt;/span&gt; &lt;span style="color: rgb(163,21,21)"&gt;"datetime"&lt;/span&gt;, &lt;span style="color: rgb(163,21,21)"&gt;"int"&lt;/span&gt;, &lt;span style="color: rgb(163,21,21)"&gt;"smallint"&lt;/span&gt;, &lt;span style="color: rgb(163,21,21)"&gt;"money"
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;Return&lt;/span&gt; &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;TextBox
&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;Height&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;28&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"
&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;Name&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(163,21,21)"&gt;"txt"&lt;/span&gt; &amp;amp; columnInfo.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;Text&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(163,21,21)"&gt;"{Binding Path="&lt;/span&gt; &amp;amp; columnInfo.ColumnName &amp;amp; &lt;span style="color: rgb(163,21,21)"&gt;"}"&lt;/span&gt; &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;Case&lt;/span&gt; &lt;span style="color: rgb(163,21,21)"&gt;"bit"
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;Return&lt;/span&gt; &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;CheckBox
&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;HorizontalContentAlignment&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;Left&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"
&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;Name&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(163,21,21)"&gt;"chk"&lt;/span&gt; &amp;amp; columnInfo.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;IsChecked&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(163,21,21)"&gt;"{Binding Path="&lt;/span&gt; &amp;amp; columnInfo.ColumnName &amp;amp; &lt;span style="color: rgb(163,21,21)"&gt;"}"&lt;/span&gt; &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&lt;/span&gt;&amp;gt;
&lt;/span&gt;                       &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; columnInfo.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                   &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;CheckBox&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;Case&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Else
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;Return&lt;/span&gt; &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;TextBox
&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;Height&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;28&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;"
&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;Name&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(163,21,21)"&gt;"txt"&lt;/span&gt; &amp;amp; columnInfo.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;MaxLength&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; columnInfo.MaxLength &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                       &lt;span style="color: rgb(185,100,100)"&gt;Text&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;=&lt;/span&gt;&lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(163,21,21)"&gt;"{Binding Path="&lt;/span&gt; &amp;amp; columnInfo.ColumnName &amp;amp; &lt;span style="color: rgb(163,21,21)"&gt;"}"&lt;/span&gt; &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Select
&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Function&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Now that we've got the UI defined I'll set the primary key field (which is a TableSchemaDataRow object) so that we can use this in our UPDATE statement as well as in the SELECT query when the user clicks the Find button on the form. Generally primary keys are surrogate keys (like auto-incrementing integers) and mean nothing to the user, so instead you may want to create another Public property that captures the search field name. Since there is only one primary key field on a table, I use the FirstOrDefault() extension method which returns the first of the sequence.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub&lt;/span&gt; SetPrimaryKey()
    &lt;span style="color: rgb(0,128,0)"&gt;'Grab the Primary Key column of the table we want to edit so we can use it in the search
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.PKField = (&lt;span style="color: rgb(0,0,255)"&gt;From&lt;/span&gt; column &lt;span style="color: rgb(0,0,255)"&gt;In&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableSchema &lt;span style="color: rgb(0,0,255)"&gt;Where&lt;/span&gt; column.IsPrimaryKey = 1).FirstOrDefault()
&lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;To create the SELECT statement, notice that I'm once again using XML literals but this time I'm not creating XML. Instead I'm creating a string by calling the XElement's .Value property. We then can create the SqlCommand and fill our untyped DataTable with the results. Setting the WPF form's DataContext sets up the data binding to the fields we specified when we generated the XAML above.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub&lt;/span&gt; btnFind_Click() &lt;span style="color: rgb(0,0,255)"&gt;Handles&lt;/span&gt; btnFind.Click
    &lt;span style="color: rgb(0,0,255)"&gt;If&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.txtSearch.Text &amp;lt;&amp;gt; &lt;span style="color: rgb(163,21,21)"&gt;""&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Then
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;Try
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;'Create the SELECT command
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;Dim&lt;/span&gt; cmdText = &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;s&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                          &lt;span style="color: rgb(85,85,85)"&gt;SELECT * FROM &lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt; 
                          &lt;span style="color: rgb(85,85,85)"&gt;WHERE &lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.PKField.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(85,85,85)"&gt;= 
&lt;/span&gt;                                &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;If&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.PKField.DataType.Contains(&lt;span style="color: rgb(163,21,21)"&gt;"char"&lt;/span&gt;), _
                                    &lt;span style="color: rgb(163,21,21)"&gt;"'"&lt;/span&gt; &amp;amp; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.txtSearch.Text &amp;amp; &lt;span style="color: rgb(163,21,21)"&gt;"'"&lt;/span&gt;, _
                                    &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.txtSearch.Text) &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                          &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;s&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;&lt;/span&gt;.Value

            &lt;span style="color: rgb(0,0,255)"&gt;Dim&lt;/span&gt; cmd &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; SqlCommand(cmdText, &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableConnection)
            &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.Table.Clear()
            &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableDataAdapter.SelectCommand = cmd
            &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableDataAdapter.Fill(&lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.Table)

            &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.DataContext = &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.Table
            &lt;span style="color: rgb(0,0,255)"&gt;Dim&lt;/span&gt; view = CollectionViewSource.GetDefaultView(&lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.Table)
            view.MoveCurrentToFirst()

        &lt;span style="color: rgb(0,0,255)"&gt;Catch&lt;/span&gt; ex &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; Exception
            MsgBox(ex.ToString)
            &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.DataContext = &lt;span style="color: rgb(0,0,255)"&gt;Nothing
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Try
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Else
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.DataContext = &lt;span style="color: rgb(0,0,255)"&gt;Nothing
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;If
&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;We want to be able to edit and save this record so we need to also generate an UPDATE command. For this example I'm only setting up the UpdateCommand on the SqlDataAdapter because we're creating a form that just edits records, but it's easy enough to create Delete and Insert commands as well. Here I'm using XML Literals again (of course! ;-)).&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;Private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub&lt;/span&gt; SetUpdateCommand()
    &lt;span style="color: rgb(0,128,0)"&gt;'Set the UpdateCommand so that we can save edited records in the table
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Dim&lt;/span&gt; cmdText = &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;s&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                  &lt;span style="color: rgb(85,85,85)"&gt;UPDATE &lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt; 
                  &lt;span style="color: rgb(85,85,85)"&gt;SET &lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;From&lt;/span&gt; column &lt;span style="color: rgb(0,0,255)"&gt;In&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableSchema _
                          &lt;span style="color: rgb(0,0,255)"&gt;Where&lt;/span&gt; column.IsPrimaryKey = 0 &lt;span style="color: rgb(0,0,255)"&gt;AndAlso&lt;/span&gt; column.DataType &amp;lt;&amp;gt; &lt;span style="color: rgb(163,21,21)"&gt;"timestamp"&lt;/span&gt; _
                          &lt;span style="color: rgb(0,0,255)"&gt;Select&lt;/span&gt; &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;c&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                                     &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; column.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(85,85,85)"&gt;= @&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; column.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                                     &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;If&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableSchema.Rows.IndexOf(column) &amp;lt; _
                                            &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableSchema.Rows.Count - 1, &lt;span style="color: rgb(163,21,21)"&gt;", "&lt;/span&gt;, &lt;span style="color: rgb(163,21,21)"&gt;""&lt;/span&gt;) &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                                 &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;c&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;&lt;/span&gt;.Value &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                  &lt;span style="color: rgb(85,85,85)"&gt;WHERE &lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.PKField.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(85,85,85)"&gt;= @&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.PKField.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                        &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;From&lt;/span&gt; column &lt;span style="color: rgb(0,0,255)"&gt;In&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableSchema _
                            &lt;span style="color: rgb(0,0,255)"&gt;Where&lt;/span&gt; column.IsPrimaryKey = 0 &lt;span style="color: rgb(0,0,255)"&gt;AndAlso&lt;/span&gt; column.DataType = &lt;span style="color: rgb(163,21,21)"&gt;"timestamp"&lt;/span&gt; _
                            &lt;span style="color: rgb(0,0,255)"&gt;Select&lt;/span&gt; &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;c&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;
&lt;/span&gt;                                     &lt;span style="color: rgb(85,85,85)"&gt;AND &lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; column.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span style="color: rgb(85,85,85)"&gt;= @&lt;span style="background: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/span&gt;&lt;/span&gt; column.ColumnName &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                                   &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;c&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;&lt;/span&gt;.Value &lt;span style="color: rgb(85,85,85)"&gt;&lt;span style="background: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/span&gt;&lt;/span&gt;                  &lt;span style="color: rgb(100,100,185)"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(132,70,70)"&gt;s&lt;/span&gt;&lt;span style="color: rgb(100,100,185)"&gt;&amp;gt;&lt;/span&gt;.Value

    &lt;span style="color: rgb(0,0,255)"&gt;Dim&lt;/span&gt; cmd &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; SqlCommand(cmdText, &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableConnection)
    &lt;span style="color: rgb(0,0,255)"&gt;Dim&lt;/span&gt; p &lt;span style="color: rgb(0,0,255)"&gt;As&lt;/span&gt; SqlParameter

    &lt;span style="color: rgb(0,0,255)"&gt;For&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Each&lt;/span&gt; column &lt;span style="color: rgb(0,0,255)"&gt;In&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableSchema
        &lt;span style="color: rgb(0,0,255)"&gt;If&lt;/span&gt; column.IsPrimaryKey = 0 &lt;span style="color: rgb(0,0,255)"&gt;AndAlso&lt;/span&gt; column.DataType = &lt;span style="color: rgb(163,21,21)"&gt;"timestamp"&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Then
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;'Note: It's recommended to use a TimeStamp column in your tables for concurrency checking
&lt;/span&gt;            p = &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; SqlParameter(&lt;span style="color: rgb(163,21,21)"&gt;"@"&lt;/span&gt; &amp;amp; column.ColumnName, SqlDbType.Timestamp)
            p.SourceVersion = DataRowVersion.Original
            p.SourceColumn = column.ColumnName
            cmd.Parameters.Add(p)
        &lt;span style="color: rgb(0,0,255)"&gt;Else
&lt;/span&gt;            p = &lt;span style="color: rgb(0,0,255)"&gt;New&lt;/span&gt; SqlParameter(&lt;span style="color: rgb(163,21,21)"&gt;"@"&lt;/span&gt; &amp;amp; column.ColumnName, _
                                 &lt;span style="color: rgb(0,0,255)"&gt;CType&lt;/span&gt;([Enum].Parse(&lt;span style="color: rgb(0,0,255)"&gt;GetType&lt;/span&gt;(SqlDbType), column.DataType, &lt;span style="color: rgb(0,0,255)"&gt;True&lt;/span&gt;), SqlDbType))
            p.SourceColumn = column.ColumnName
            p.SourceVersion = DataRowVersion.Current
            cmd.Parameters.Add(p)
        &lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;If
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Next

&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;Me&lt;/span&gt;.TableDataAdapter.UpdateCommand = cmd
&lt;span style="color: rgb(0,0,255)"&gt;End&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;Sub&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;One important note here is that when I create the UpdateCommand, I'm assuming that concurrency checking is being done with a TimeStamp field (which I've added to my copy of Northwind) but you can also create the "long version" where it checks original against current values as well.&lt;/p&gt;
&lt;p&gt;So now we can simply set the TableName property of this form and it will dynamically generate the UI, load the data when we click the Find button, and allow us to save our changes back to the database. Try modifying your database table's schema and running it again without recompiling. Slick.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://blogs.msdn.com/photos/bethmassi/images/8649289/original.aspx"&gt; &lt;/p&gt;
&lt;p&gt;I've &lt;a href="http://code.msdn.microsoft.com/dynamicWPF" target="_blank"&gt;uploaded this project onto CodeGallery&lt;/a&gt; with both forms (this one and the one we did in the last post) so have a look. You'll need to download 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 here&lt;/a&gt; first. &lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8649441" 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/XML/default.aspx">XML</category></item><item><title>Dynamic UI with WPF and LINQ</title><link>http://blogs.msdn.com/bethmassi/archive/2008/06/12/dynamic-ui-with-wpf-and-linq.aspx</link><pubDate>Fri, 13 Jun 2008 02:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8593839</guid><dc:creator>Beth Massi</dc:creator><slash:comments>42</slash:comments><comments>http://blogs.msdn.com/bethmassi/comments/8593839.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bethmassi/commentrss.aspx?PostID=8593839</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bethmassi/rsscomments.aspx?PostID=8593839</wfw:comment><description>&lt;P&gt;Lately I've been getting my hands deep into WPF with my line-of-business (LOB)/data-based application mind set. I'm taking a different approach to the technology resisting the urge to put on my amateur-designer hat and instead purely focus on data, data-binding, formatting controls, and some basic layout. (Yes before you ask, I have started producing the WPF forms over data videos!) &lt;/P&gt;
&lt;P&gt;Today I wanted to play with dynamically creating XAML and loading it at runtime. This was really easy using XML literals and XML namespace imports. Let me show you what I mean. You can load and save XAML at runtime using the System.Windows.Markup.XamlReader and System.Windows.Markup.XamlWriter classes. Create a new WPF project and in the Window1 code-behind you can do this:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Imports&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(185,100,100)"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Imports&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(185,100,100)"&gt;xmlns:x&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Imports&lt;/SPAN&gt; System.Windows.Markup

&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Class&lt;/SPAN&gt; Window1

    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Sub&lt;/SPAN&gt; Window1_Loaded() &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Handles&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;MyBase&lt;/SPAN&gt;.Loaded

        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Dim&lt;/SPAN&gt; UI = &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;Label&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;Label1&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;This is COOL!&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;

&lt;/SPAN&gt;        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Me&lt;/SPAN&gt;.Content = XamlReader.Load(UI.CreateReader())

    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Sub
End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Class&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 it:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/bethmassi/images/8593785/original.aspx" mce_src="http://blogs.msdn.com/photos/bethmassi/images/8593785/original.aspx"&gt; &lt;/P&gt;
&lt;P&gt;There are a lot of possibilities here. For instance, wouldn't it be nice to automatically generate all your maintenance screens in your business apps? When I say "maintenance" I mean all those simpler lookup data tables or contact tables. Even a customer contact form is usually pretty basic. Instead of handing those screens to the newbie or the junior on the team why not just generate them all at runtime based on your object model or database schema?&lt;/P&gt;
&lt;P&gt;Admittedly this isn't something that is only unique to WPF. You could do this in Winforms as well but it was an exercise in coding the layout by hand. WPF makes this a breeze because we can define one piece of XAML and we can construct it from a single LINQ query. You can use reflection to look at your object model but if it's really simple and maps one-to-one to your database table anyway you can just create a table (or a stored proc) that contains the schema (or meta-data) of all of your maintenance tables. For instance to generate a simple UI we would probably want to obtain at minimum the following properties for each column in a table:&lt;/P&gt;
&lt;P&gt;ColumnName&lt;BR&gt;DataType&lt;BR&gt;MaxLength&lt;BR&gt;IsPrimaryKey&lt;/P&gt;
&lt;P&gt;You can either create a meta-data table in your database or a stored proc that returns the info from the information schema (check permissions for the stored proc if you go that route). I was playing with the stored proc idea because then if I make a change to my database, I don't need to update my code necessarily. So for this example I created a stored proc in the Northwind database called GetTableSchema:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;CREATE PROCEDURE &lt;/SPAN&gt;dbo.GetTableSchema
    (
    @table &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;varchar&lt;/SPAN&gt;(50)
    )    
&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;AS
SELECT 
&lt;/SPAN&gt;c.table_name &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;As &lt;/SPAN&gt;TableName, 
c.column_name &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;As &lt;/SPAN&gt;ColumnName, 
c.data_type &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;As &lt;/SPAN&gt;DataType, 
c.character_maximum_length &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;As &lt;/SPAN&gt;MaxLength,
    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;COALESCE &lt;/SPAN&gt;(
    ( &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;SELECT 
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;CASE &lt;/SPAN&gt;cu.column_name
            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;WHEN null THEN &lt;/SPAN&gt;0
            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;ELSE &lt;/SPAN&gt;1
        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;END
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;FROM &lt;/SPAN&gt;information_schema.constraint_column_usage cu
    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;INNER join &lt;/SPAN&gt;information_schema.table_constraints ct
    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;ON &lt;/SPAN&gt;ct.constraint_name = cu.constraint_name
    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;WHERE 
&lt;/SPAN&gt;    ct.constraint_type = &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;'PRIMARY KEY' 
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;AND &lt;/SPAN&gt;ct.table_name = c.table_name
    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;AND &lt;/SPAN&gt;cu.column_name = c.column_name 
    ),0) &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;AS &lt;/SPAN&gt;IsPrimaryKey
&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;FROM &lt;/SPAN&gt;information_schema.columns c
&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;INNER JOIN &lt;/SPAN&gt;information_schema.tables t
&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;ON &lt;/SPAN&gt;c.table_name = t.table_name
&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;WHERE &lt;/SPAN&gt;@table = t.table_name &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;and 
&lt;/SPAN&gt;      (t.table_type = &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;'BASE TABLE' &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;and not 
&lt;/SPAN&gt;      (t.table_name = &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;'dtproperties'&lt;/SPAN&gt;) &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;and not 
&lt;/SPAN&gt;      (t.table_name = &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;'sysdiagrams'&lt;/SPAN&gt;))
&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;ORDER BY &lt;/SPAN&gt;c.table_name, c.ordinal_position&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;I then added a new "LINQ to SQL classes" item to my project and dragged Customer onto the design surface (for this example that's what we'll be editing) from the Northwind database I had connected to in my Server Explorer. I then expanded the "Stored Procedures" and dragged the above procedure onto the methods pane. Next I manually created an object on the design surface called TableSchema that contained the same properties as the fields I'm returning from the stored proc. Once I have that all set up I can now map the result type of the stored proc to the TableSchema class:&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/bethmassi/images/8593821/640x458.aspx" mce_src="http://blogs.msdn.com/photos/bethmassi/images/8593821/640x458.aspx"&gt; &lt;/P&gt;
&lt;P&gt;Okay now that we have that set up we can get back to the fun stuff. I created a simple lookup textbox and "Find" and "Save" buttons at a fixed area at the top of my WPF window. Under that I dragged a ContentControl onto the form and named it DynamicContent. We're going to generate the content here from the Customer schema and bind to the customer object that is returned from our LINQ query when we click find. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Window&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; x&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt;Class&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="Window1"
&lt;/SPAN&gt;   &lt;SPAN style="COLOR: rgb(255,0,0)"&gt; xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
&lt;/SPAN&gt;   &lt;SPAN style="COLOR: rgb(255,0,0)"&gt; xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"
&lt;/SPAN&gt;   &lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Title&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="Window1"&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="Window1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; SizeToContent&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="WidthAndHeight" &amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;    &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="MainGrid"&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt; &amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;        &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Grid.RowDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;            &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;RowDefinition&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="10*" /&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;            &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;RowDefinition&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="60*" /&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;        &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Grid.RowDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;        &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="StackPanel1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Orientation&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="Horizontal"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="3"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="Top"&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;            &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="28"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="Label1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="84"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="Right"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; FontWeight&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="Bold"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;            &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;TextBox&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="25"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="txtSearch"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="120"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;ALFKI&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;TextBox&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;            &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="25"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="btnFind"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="75"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Find&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;            &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="25"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="btnSave"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="75"&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Save&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;        &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;        &lt;/SPAN&gt;&lt;STRONG&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;ContentControl&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Grid.Row&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;="DynamicContent"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(255,0,0)"&gt; Margin&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&lt;STRONG&gt;="3" /&amp;gt;&lt;/STRONG&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;    &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Window&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&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;First let's generate the UI in the Load event of our form. The first thing is to add the appropriate Imports at the top of the file and then we can generate our UI. (I also have handlers here for the actual loading and saving of the customer.) &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Imports&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(185,100,100)"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Imports&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(185,100,100)"&gt;xmlns:x&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Imports&lt;/SPAN&gt; System.Windows.Markup

&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Class&lt;/SPAN&gt; Window1

    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Dim&lt;/SPAN&gt; db &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;As&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;New&lt;/SPAN&gt; NorthwindDataContext
    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Dim&lt;/SPAN&gt; CustomerData &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;As&lt;/SPAN&gt; Customer

    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Sub&lt;/SPAN&gt; Window1_Loaded() &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Handles&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;MyBase&lt;/SPAN&gt;.Loaded

        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Dim&lt;/SPAN&gt; customerSchema = db.GetTableSchema(&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"Customers"&lt;/SPAN&gt;).ToList()

        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Dim&lt;/SPAN&gt; UI = &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;Grid&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;xmlns:x&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"
&lt;/SPAN&gt;                     &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;                     &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;Grid.ColumnDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;                         &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;ColumnDefinition&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;100*&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;/&amp;gt;
&lt;/SPAN&gt;                         &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;ColumnDefinition&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;200*&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;/&amp;gt;
&lt;/SPAN&gt;                     &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;Grid.ColumnDefinitions&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;                     &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;StackPanel&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;StackLabels&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;3&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;                         &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;From&lt;/SPAN&gt; column &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;In&lt;/SPAN&gt; customerSchema _
                             &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Where&lt;/SPAN&gt; column.IsPrimaryKey = 0 _
                             &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Select&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;Label
&lt;/SPAN&gt;                                        &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;28&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"
&lt;/SPAN&gt;                                        &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; column.ColumnName &amp;amp; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"Label"&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/SPAN&gt;&lt;/SPAN&gt;                                        &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;Right&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;                                        &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; column.ColumnName &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;&lt;/SPAN&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;Label&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/SPAN&gt;&lt;/SPAN&gt;                     &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;                     &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;StackPanel&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Grid.Column&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;1&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;StackFields&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;3&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;                         &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;From&lt;/SPAN&gt; column &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;In&lt;/SPAN&gt; customerSchema _
                             &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Where&lt;/SPAN&gt; column.IsPrimaryKey = 0 _
                             &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Select&lt;/SPAN&gt; GetUIElement(column) &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/SPAN&gt;&lt;/SPAN&gt;                     &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;                 &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;

&lt;/SPAN&gt;        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Me&lt;/SPAN&gt;.DynamicContent.Content = XamlReader.Load(UI.CreateReader)

    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Sub

&lt;/SPAN&gt;    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Function&lt;/SPAN&gt; GetUIElement(&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;ByVal&lt;/SPAN&gt; column &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;As&lt;/SPAN&gt; TableSchema) &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;As&lt;/SPAN&gt; XElement
        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Select&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Case&lt;/SPAN&gt; column.DataType
            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Case&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"datetime"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"int"
&lt;/SPAN&gt;                &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Return&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;TextBox
&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;28&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"
&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"txt"&lt;/SPAN&gt; &amp;amp; column.ColumnName &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/SPAN&gt;&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"{Binding Path="&lt;/SPAN&gt; &amp;amp; column.ColumnName &amp;amp; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;", ValidatesOnDataErrors=True}"&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&lt;/SPAN&gt;/&amp;gt;
&lt;/SPAN&gt;            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Case&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"bit"
&lt;/SPAN&gt;                &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Return&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;CheckBox
&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;HorizontalContentAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;Left&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"
&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"chk"&lt;/SPAN&gt; &amp;amp; column.ColumnName &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/SPAN&gt;&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;IsChecked&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"{Binding Path="&lt;/SPAN&gt; &amp;amp; column.ColumnName &amp;amp; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;", ValidatesOnDataErrors=True}"&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&lt;/SPAN&gt;&amp;gt;
&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; column.ColumnName &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/SPAN&gt;&lt;/SPAN&gt;                       &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;CheckBox&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;gt;
&lt;/SPAN&gt;            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Case&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Else
&lt;/SPAN&gt;                &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Return&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(132,70,70)"&gt;TextBox
&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Height&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;28&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;"
&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"txt"&lt;/SPAN&gt; &amp;amp; column.ColumnName &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/SPAN&gt;&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;MaxLength&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; column.MaxLength &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;
&lt;/SPAN&gt;&lt;/SPAN&gt;                           &lt;SPAN style="COLOR: rgb(185,100,100)"&gt;Text&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;&amp;lt;%=&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"{Binding Path="&lt;/SPAN&gt; &amp;amp; column.ColumnName &amp;amp; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;", ValidatesOnDataErrors=True}"&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(85,85,85)"&gt;&lt;SPAN style="BACKGROUND: rgb(255,254,191)"&gt;%&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(100,100,185)"&gt;&lt;/SPAN&gt;/&amp;gt;
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Select
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Function

&lt;/SPAN&gt;    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Sub&lt;/SPAN&gt; btnFind_Click() &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Handles&lt;/SPAN&gt; btnFind.Click
        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;If&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Me&lt;/SPAN&gt;.txtSearch.Text &amp;lt;&amp;gt; &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;""&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Then
&lt;/SPAN&gt;            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Me&lt;/SPAN&gt;.CustomerData = (&lt;SPAN style="COLOR: rgb(0,0,255)"&gt;From&lt;/SPAN&gt; cust &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;In&lt;/SPAN&gt; db.Customers _
                              &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Where&lt;/SPAN&gt; cust.CustomerID = &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Me&lt;/SPAN&gt;.txtSearch.Text).FirstOrDefault()

            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Me&lt;/SPAN&gt;.DataContext = &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Me&lt;/SPAN&gt;.CustomerData
        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Else
&lt;/SPAN&gt;            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Me&lt;/SPAN&gt;.DataContext = &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Nothing
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;If
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Sub

&lt;/SPAN&gt;    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Private&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Sub&lt;/SPAN&gt; btnSave_Click() &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Handles&lt;/SPAN&gt; btnSave.Click
        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;If&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Me&lt;/SPAN&gt;.DataContext &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;IsNot&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Nothing&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Then
&lt;/SPAN&gt;            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Try
&lt;/SPAN&gt;                db.SubmitChanges()
                MsgBox(&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"Saved"&lt;/SPAN&gt;)

            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Catch&lt;/SPAN&gt; ex &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;As&lt;/SPAN&gt; Exception
                MsgBox(ex.ToString)
            &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Try
&lt;/SPAN&gt;        &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;If
&lt;/SPAN&gt;    &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Sub
End&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(0,0,255)"&gt;Class&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;The stored proc will work for any table contained in the database, so we could even abstract this further, and I obviously didn't get very fancy with the UI -- but I think you get the idea. &lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/bethmassi/images/8593834/original.aspx" mce_src="http://blogs.msdn.com/photos/bethmassi/images/8593834/original.aspx"&gt; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;UPDATE: Read the &lt;/STRONG&gt;&lt;A class="" href="http://blogs.msdn.com/bethmassi/archive/2008/06/24/dynamic-data-entry-with-wpf-and-linq.aspx" target=_blank mce_href="http://blogs.msdn.com/bethmassi/archive/2008/06/24/dynamic-data-entry-with-wpf-and-linq.aspx"&gt;&lt;STRONG&gt;latest post on dynamic data entry&lt;/STRONG&gt;&lt;/A&gt;&lt;STRONG&gt; and &lt;/STRONG&gt;&lt;A class="" href="http://code.msdn.microsoft.com/dynamicWPF" target=_blank mce_href="http://code.msdn.microsoft.com/dynamicWPF"&gt;&lt;STRONG&gt;download the code samples&lt;/STRONG&gt;&lt;/A&gt;&lt;STRONG&gt;.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8593839" 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/XML/default.aspx">XML</category></item></channel></rss>