Upgrade framework winforms-outlook article (#1280)

* upgrade winforms-outlook article

* change readme name; add description

* change readme name; add description
This commit is contained in:
Andy (Steve) De George
2022-01-24 13:07:43 -06:00
committed by GitHub
parent 436afcf024
commit 0358914363
8 changed files with 420 additions and 157 deletions
@@ -1,6 +1,7 @@
--- ---
title: Create a Multipane User Interface title: Create a Multipane User Interface
ms.date: "03/30/2017" description: Describes how to layout Windows Forms controls to mimic a Microsoft Outlook email application.
ms.date: 01/21/2022
dev_langs: dev_langs:
- "csharp" - "csharp"
- "vb" - "vb"
@@ -14,162 +15,53 @@ helpviewer_keywords:
ms.assetid: e79f6bcc-3740-4d1e-b46a-c5594d9b7327 ms.assetid: e79f6bcc-3740-4d1e-b46a-c5594d9b7327
--- ---
# How to: Create a Multipane User Interface with Windows Forms # How to: Create a Multipane User Interface with Windows Forms
In the following procedure, you will create a multipane user interface that is similar to the one used in Microsoft Outlook, with a **Folder** list, a **Messages** pane, and a **Preview** pane. This arrangement is achieved chiefly through docking controls with the form.
By arranging controls on a form, you can create a multi-pane user interface that's similar to the one used in Microsoft Outlook, with a **Folder** list, a **Messages** pane, and a **Preview** pane. This arrangement is achieved chiefly through docking controls with the form.
When you dock a control, you determine which edge of the parent container a control is fastened to. Thus, if you set the <xref:System.Windows.Forms.SplitContainer.Dock%2A> property to <xref:System.Windows.Forms.DockStyle.Right>, the right edge of the control will be docked to the right edge of its parent control. Additionally, the docked edge of the control is resized to match that of its container control. For more information about how the <xref:System.Windows.Forms.SplitContainer.Dock%2A> property works, see [How to: Dock Controls on Windows Forms](how-to-dock-controls-on-windows-forms.md).
When you dock a control, you determine which edge of the parent container a control is fastened to. If you set the <xref:System.Windows.Forms.SplitContainer.Dock%2A> property to <xref:System.Windows.Forms.DockStyle.Right>, the right edge of the control will be docked to the right edge of its parent control. Additionally, the docked edge of the control is resized to match that of its container control. For more information about how the <xref:System.Windows.Forms.SplitContainer.Dock%2A> property works, see [How to: Dock Controls on Windows Forms](how-to-dock-controls-on-windows-forms.md).
This procedure focuses on arranging the <xref:System.Windows.Forms.SplitContainer> and the other controls on the form, not on adding functionality to make the application mimic Microsoft Outlook.
This procedure focuses on arranging the <xref:System.Windows.Forms.SplitContainer> and the other controls on the form, not on adding functionality to make the application mimic Microsoft Outlook.
To create this user interface, you place all the controls within a <xref:System.Windows.Forms.SplitContainer> control, which contains a <xref:System.Windows.Forms.TreeView> control in the left-hand panel. The right-hand panel of the <xref:System.Windows.Forms.SplitContainer> control contains a second <xref:System.Windows.Forms.SplitContainer> control with a <xref:System.Windows.Forms.ListView> control above a <xref:System.Windows.Forms.RichTextBox> control. These <xref:System.Windows.Forms.SplitContainer> controls enable independent resizing of the other controls on the form. You can adapt the techniques in this procedure to craft custom user interfaces of your own.
:::image type="content" source="media/how-to-create-a-multipane-user-interface-with-windows-forms/form.png" alt-text="A form that's designed to look like an Outlook mail window.":::
### To create an Outlook-style user interface programmatically
To create this user interface, you place all the controls within a <xref:System.Windows.Forms.SplitContainer> control. The `SplitContainer` contains a <xref:System.Windows.Forms.TreeView> control in the left-hand panel and another `SplitContainer` on the right-hand panel. The second `SplitContainer` contains a <xref:System.Windows.Forms.ListView> control on top and a <xref:System.Windows.Forms.RichTextBox> control on the bottom.
1. Within a form, declare each control that comprises your user interface. For this example, use the <xref:System.Windows.Forms.TreeView>, <xref:System.Windows.Forms.ListView>, <xref:System.Windows.Forms.SplitContainer>, and <xref:System.Windows.Forms.RichTextBox> controls to mimic the Microsoft Outlook user interface.
These <xref:System.Windows.Forms.SplitContainer> controls enable independent resizing of the other controls on the form. You can adapt the techniques in this procedure to craft custom user interfaces of your own.
```vb
Private WithEvents treeView1 As System.Windows.Forms.TreeView ## Control layout
Private WithEvents listView1 As System.Windows.Forms.ListView
Private WithEvents richTextBox1 As System.Windows.Forms.RichTextBox The following table describes how the controls are configured to mimic Microsoft Outlook:
Private WithEvents splitContainer1 As _
System.Windows.Forms.SplitContainer | Control | Property | Value |
Private WithEvents splitContainer2 As _ |----------------|------------------|--------------------------------------------------|
System.Windows.Forms.SplitContainer | SplitContainer | Name | `splitContainer1` |
``` | | Dock | `Fill` |
| | TabIndex | `4` |
```csharp | | SplitterWidth | `4` |
private System.Windows.Forms.TreeView treeView1; | | SplitterDistance | `100` |
private System.Windows.Forms.ListView listView1; | | Panel1.Controls | Add the `treeView1` control to this panel. |
private System.Windows.Forms.RichTextBox richTextBox1; | | Panel2.Controls | Add the `splitContainer2` control to this panel. |
private System.Windows.Forms. SplitContainer splitContainer2; | TreeView | Name | `treeView1` |
private System.Windows.Forms. SplitContainer splitContainer1; | | Dock | `Fill` |
``` | | TabIndex | `0` |
| | Nodes | Add a new node named `Node0` |
2. Create a procedure that defines your user interface. The following code sets the properties so that the form will resemble the user interface in Microsoft Outlook. However, by using other controls or docking them differently, it is just as easy to create other user interfaces that are equally flexible. | SplitContainer | Name | `splitContainer2` |
| | Dock | `Fill` |
```vb | | TabIndex | `1` |
Public Sub CreateOutlookUI() | | SplitterWidth | `4` |
' Create an instance of each control being used. | | SplitterDistance | `150` |
Me.components = New System.ComponentModel.Container() | | Orientation | `Horizontal` |
Me.treeView1 = New System.Windows.Forms.TreeView() | | Panel1.Controls | Add the `listView1` control to this panel. |
Me.listView1 = New System.Windows.Forms.ListView() | | Panel2.Controls | Add the `richTextBox1` control to this panel. |
Me.richTextBox1 = New System.Windows.Forms.RichTextBox() | ListView | Name | `listView1` |
Me.splitContainer1 = New System.Windows.Forms.SplitContainer() | | Dock | `Fill` |
Me.splitContainer2= New System.Windows.Forms. SplitContainer() | | TabIndex | `2` |
| | Items | Add a new item and set the text to `item1`. |
' Should you develop this into a working application, | RichTextBox | Name | `richTextBox1` |
' use the AddHandler method to hook up event procedures here. | | Dock | `Fill` |
| | TabIndex | `3` |
' Set properties of TreeView control. | | Text | `richTextBox1` |
' Use the With statement to avoid repetitive code.
With Me.treeView1
.Dock = System.Windows.Forms.DockStyle.Fill
.TabIndex = 0
.Nodes.Add("treeView")
End With
' Set properties of ListView control.
With Me.listView1
.Dock = System.Windows.Forms.DockStyle.Top
.TabIndex = 2
.Items.Add("listView")
End With
' Set properties of RichTextBox control.
With Me.richTextBox1
.Dock = System.Windows.Forms.DockStyle.Fill
.TabIndex = 3
.Text = "richTextBox1"
End With
' Set properties of the first SplitContainer control.
With Me.splitContainer1
.Dock = System.Windows.Forms.DockStyle.Fill
.TabIndex = 1
.SplitterWidth = 4
.SplitterDistance = 150
.Orientation = Orientation.Horizontal
.Panel1.Controls.Add(Me.listView1)
.Panel2.Controls.Add(Me.richTextBox1)
End With
' Set properties of the second SplitContainer control.
With Me.splitContainer2
.Dock = System.Windows.Forms.DockStyle.Fill
.TabIndex = 4
.SplitterWidth = 4
.SplitterDistance = 100
.Panel1.Controls.Add(Me.treeView1)
.Panel2.Controls.Add(Me.SplitContainer1)
End With
' Add the main SplitContainer control to the form.
Me.Controls.Add(Me.splitContainer2)
Me.Text = "Intricate UI Example"
End Sub
```
```csharp
public void createOutlookUI()
{
// Create an instance of each control being used.
treeView1 = new System.Windows.Forms.TreeView();
listView1 = new System.Windows.Forms.ListView();
richTextBox1 = new System.Windows.Forms.RichTextBox();
splitContainer2 = new System.Windows.Forms.SplitContainer();
splitContainer1 = new System.Windows.Forms.SplitContainer();
// Insert code here to hook up event methods.
// Set properties of TreeView control.
treeView1.Dock = System.Windows.Forms.DockStyle.Fill;
treeView1.TabIndex = 0;
treeView1.Nodes.Add("treeView");
// Set properties of ListView control.
listView1.Dock = System.Windows.Forms.DockStyle.Top;
listView1.TabIndex = 2;
listView1.Items.Add("listView");
// Set properties of RichTextBox control.
richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
richTextBox1.TabIndex = 3;
richTextBox1.Text = "richTextBox1";
// Set properties of first SplitContainer control.
splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
splitContainer2.TabIndex = 1;
splitContainer2.SplitterWidth = 4;
splitContainer2.SplitterDistance = 150;
splitContainer2.Orientation = Orientation.Horizontal;
splitContainer2.Panel1.Controls.Add(this.listView1);
splitContainer2.Panel1.Controls.Add(this.richTextBox1);
// Set properties of second SplitContainer control.
splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
splitContainer2.TabIndex = 4;
splitContainer2.SplitterWidth = 4;
splitContainer2.SplitterDistance = 100;
splitContainer2.Panel1.Controls.Add(this.treeView1);
splitContainer2.Panel1.Controls.Add(this.splitContainer1);
// Add the main SplitContainer control to the form.
this.Controls.Add(this.splitContainer2);
this.Text = "Intricate UI Example";
}
```
3. In Visual Basic, add a call to the procedure you just created in the `New()` procedure. In Visual C#, add this line of code to the constructor for the form class.
```vb
' Add this to the New procedure.
CreateOutlookUI()
```
```csharp
// Add this to the form class's constructor.
createOutlookUI();
```
## See also ## See also
- <xref:System.Windows.Forms.SplitContainer> - <xref:System.Windows.Forms.SplitContainer>
@@ -0,0 +1,147 @@
namespace project
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("Node0");
System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("item1");
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.treeView1 = new System.Windows.Forms.TreeView();
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
this.listView1 = new System.Windows.Forms.ListView();
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
this.splitContainer2.Panel1.SuspendLayout();
this.splitContainer2.Panel2.SuspendLayout();
this.splitContainer2.SuspendLayout();
this.SuspendLayout();
//
// splitContainer1
//
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
this.splitContainer1.Name = "splitContainer1";
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.treeView1);
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.splitContainer2);
this.splitContainer1.Size = new System.Drawing.Size(448, 366);
this.splitContainer1.SplitterDistance = 100;
this.splitContainer1.TabIndex = 1;
//
// treeView1
//
this.treeView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.treeView1.Location = new System.Drawing.Point(0, 0);
this.treeView1.Name = "treeView1";
treeNode1.Name = "Node0";
treeNode1.Text = "Node0";
this.treeView1.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
treeNode1});
this.treeView1.Size = new System.Drawing.Size(100, 366);
this.treeView1.TabIndex = 0;
//
// splitContainer2
//
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer2.Location = new System.Drawing.Point(0, 0);
this.splitContainer2.Name = "splitContainer2";
this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
//
// splitContainer2.Panel1
//
this.splitContainer2.Panel1.Controls.Add(this.listView1);
//
// splitContainer2.Panel2
//
this.splitContainer2.Panel2.Controls.Add(this.richTextBox1);
this.splitContainer2.Size = new System.Drawing.Size(344, 366);
this.splitContainer2.SplitterDistance = 156;
this.splitContainer2.TabIndex = 1;
//
// listView1
//
this.listView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.listView1.HideSelection = false;
this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem1});
this.listView1.Location = new System.Drawing.Point(0, 0);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(344, 156);
this.listView1.TabIndex = 2;
this.listView1.UseCompatibleStateImageBehavior = false;
//
// richTextBox1
//
this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.richTextBox1.Location = new System.Drawing.Point(0, 0);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(344, 206);
this.richTextBox1.TabIndex = 3;
this.richTextBox1.Text = "richTextBox1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(448, 366);
this.Controls.Add(this.splitContainer1);
this.Margin = new System.Windows.Forms.Padding(2);
this.Name = "Form1";
this.Text = "Form1";
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
this.splitContainer1.ResumeLayout(false);
this.splitContainer2.Panel1.ResumeLayout(false);
this.splitContainer2.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
this.splitContainer2.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.TreeView treeView1;
private System.Windows.Forms.SplitContainer splitContainer2;
private System.Windows.Forms.ListView listView1;
private System.Windows.Forms.RichTextBox richTextBox1;
}
}
@@ -0,0 +1,16 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
namespace project
{
public partial class Form1 : Form
{
//Windows Form application
public Form1()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace project
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{50B5AD53-1181-46C6-91EE-0E65BADF34E1}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>project</RootNamespace>
<AssemblyName>project</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<GenerateResourceMSBuildArchitecture>CurrentArchitecture</GenerateResourceMSBuildArchitecture>
<GenerateResourceMSBuildRuntime>CurrentRuntime</GenerateResourceMSBuildRuntime>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1 @@
This code is used to generate the screenshot referenced in the parent article.