Merge pull request #1286 from dotnet/publish-21568

This commit is contained in:
Bill Wagner
2022-01-25 08:19:42 -05:00
committed by GitHub
24 changed files with 578 additions and 226 deletions
@@ -1,6 +1,7 @@
---
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:
- "csharp"
- "vb"
@@ -14,162 +15,53 @@ helpviewer_keywords:
ms.assetid: e79f6bcc-3740-4d1e-b46a-c5594d9b7327
---
# 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.
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).
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.
### To create an Outlook-style user interface programmatically
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.
```vb
Private WithEvents treeView1 As System.Windows.Forms.TreeView
Private WithEvents listView1 As System.Windows.Forms.ListView
Private WithEvents richTextBox1 As System.Windows.Forms.RichTextBox
Private WithEvents splitContainer1 As _
System.Windows.Forms.SplitContainer
Private WithEvents splitContainer2 As _
System.Windows.Forms.SplitContainer
```
```csharp
private System.Windows.Forms.TreeView treeView1;
private System.Windows.Forms.ListView listView1;
private System.Windows.Forms.RichTextBox richTextBox1;
private System.Windows.Forms. SplitContainer splitContainer2;
private System.Windows.Forms. SplitContainer splitContainer1;
```
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.
```vb
Public Sub CreateOutlookUI()
' Create an instance of each control being used.
Me.components = New System.ComponentModel.Container()
Me.treeView1 = New System.Windows.Forms.TreeView()
Me.listView1 = New System.Windows.Forms.ListView()
Me.richTextBox1 = New System.Windows.Forms.RichTextBox()
Me.splitContainer1 = New System.Windows.Forms.SplitContainer()
Me.splitContainer2= New System.Windows.Forms. SplitContainer()
' Should you develop this into a working application,
' use the AddHandler method to hook up event procedures here.
' Set properties of TreeView control.
' 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();
```
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. 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.
:::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 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.
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.
## Control layout
The following table describes how the controls are configured to mimic Microsoft Outlook:
| Control | Property | Value |
|----------------|------------------|--------------------------------------------------|
| SplitContainer | Name | `splitContainer1` |
| | Dock | `Fill` |
| | TabIndex | `4` |
| | SplitterWidth | `4` |
| | SplitterDistance | `100` |
| | Panel1.Controls | Add the `treeView1` control to this panel. |
| | Panel2.Controls | Add the `splitContainer2` control to this panel. |
| TreeView | Name | `treeView1` |
| | Dock | `Fill` |
| | TabIndex | `0` |
| | Nodes | Add a new node named `Node0` |
| SplitContainer | Name | `splitContainer2` |
| | Dock | `Fill` |
| | TabIndex | `1` |
| | SplitterWidth | `4` |
| | SplitterDistance | `150` |
| | Orientation | `Horizontal` |
| | Panel1.Controls | Add the `listView1` control to this panel. |
| | Panel2.Controls | Add the `richTextBox1` control to this panel. |
| ListView | Name | `listView1` |
| | Dock | `Fill` |
| | TabIndex | `2` |
| | Items | Add a new item and set the text to `item1`. |
| RichTextBox | Name | `richTextBox1` |
| | Dock | `Fill` |
| | TabIndex | `3` |
| | Text | `richTextBox1` |
## See also
- <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.
@@ -33,6 +33,7 @@ helpviewer_keywords:
ms.assetid: 67cce290-ca26-4c41-a797-b68aabc45479
---
# XAML Syntax In Detail
This topic defines the terms that are used to describe the elements of XAML syntax. These terms are used frequently throughout the remainder of this documentation, both for WPF documentation specifically and for the other frameworks that use XAML or the basic XAML concepts enabled by the XAML language support at the System.Xaml level. This topic expands on the basic terminology introduced in the topic [XAML in WPF](xaml-in-wpf.md).
This topic defines the terms that are used to describe the elements of XAML syntax. These terms are used frequently throughout the remainder of this documentation, both for WPF documentation specifically and for the other frameworks that use XAML or the basic XAML concepts enabled by the XAML language support at the System.Xaml level. This topic expands on the basic terminology introduced in the topic [XAML Overview (WPF)](/dotnet/desktop-wpf/fundamentals/xaml).
@@ -69,7 +70,47 @@ For example, the following example is object element syntax that instantiates a
The following example is object element syntax that also includes XAML content property syntax. The inner text contained within will be used to set the <xref:System.Windows.Controls.TextBox> XAML content property, <xref:System.Windows.Controls.TextBox.Text%2A>.
[!code-xaml[XAMLOvwSupport#ThisIsATextBox](~/samples/snippets/csharp/VS_Snippets_Wpf/XAMLOvwSupport/CSharp/Page1.xaml#thisisatextbox)]
For more information about the XAML language specification, download [\[MS-XAML\]](https://download.microsoft.com/download/0/A/6/0A6F7755-9AF5-448B-907D-13985ACCF53E/[MS-XAML].pdf) from the Microsoft Download Center.
<a name="xaml_and_clr"></a>
## XAML and CLR
XAML is a markup language. The common language runtime (CLR), as implied by its name, enables runtime execution. XAML is not by itself one of the common languages that is directly consumed by the CLR runtime. Instead, you can think of XAML as supporting its own type system. The particular XAML parsing system that is used by WPF is built on the CLR and the CLR type system. XAML types are mapped to CLR types to instantiate a run time representation when the XAML for WPF is parsed. For this reason, the remainder of discussion of syntax in this document will include references to the CLR type system, even though the equivalent syntax discussions in the XAML language specification do not. (Per the XAML language specification level, XAML types could be mapped to any other type system, which does not have to be the CLR, but that would require the creation and use of a different XAML parser.)
#### Members of Types and Class Inheritance
Properties and events as they appear as XAML members of a WPF type are often inherited from base types. For example, consider this example: `<Button Background="Blue" .../>`. The <xref:System.Windows.Controls.Control.Background%2A> property is not an immediately declared property on the <xref:System.Windows.Controls.Button> class, if you were to look at the class definition, reflection results, or the documentation. Instead, <xref:System.Windows.Controls.Control.Background%2A> is inherited from the base <xref:System.Windows.Controls.Control> class.
The class inheritance behavior of WPF XAML elements is a significant departure from a schema-enforced interpretation of XML markup. Class inheritance can become complex, particularly when intermediate base classes are abstract, or when interfaces are involved. This is one reason that the set of XAML elements and their permissible attributes is difficult to represent accurately and completely using the schema types that are typically used for XML programming, such as DTD or XSD format. Another reason is that extensibility and type-mapping features of the XAML language itself preclude completeness of any fixed representation of the permissible types and members.
<a name="object_element_syntax"></a>
## Object Element Syntax
*Object element syntax* is the XAML markup syntax that instantiates a CLR class or structure by declaring an XML element. This syntax resembles the element syntax of other markup languages such as HTML. Object element syntax begins with a left angle bracket (\<), followed immediately by the type name of the class or structure being instantiated. Zero or more spaces can follow the type name, and zero or more attributes may also be declared on the object element, with one or more spaces separating each attribute name="value" pair. Finally, one of the following must be true:
- The element and tag must be closed by a forward slash (/) followed immediately by a right angle bracket (>).
- The opening tag must be completed by a right angle bracket (>). Other object elements, property elements, or inner text, can follow the opening tag. Exactly what content may be contained here is typically constrained by the object model of the element. The equivalent closing tag for the object element must also exist, in proper nesting and balance with other opening and closing tag pairs.
XAML as implemented by .NET has a set of rules that map object elements into types, attributes into properties or events, and XAML namespaces to CLR namespaces plus assembly. For WPF and .NET, XAML object elements map to .NET types as defined in referenced assemblies, and the attributes map to members of those types. When you reference a CLR type in XAML, you have access to the inherited members of that type as well.
For example, the following example is object element syntax that instantiates a new instance of the <xref:System.Windows.Controls.Button> class, and also specifies a <xref:System.Windows.FrameworkElement.Name%2A> attribute and a value for that attribute:
[!code-xaml[XAMLOvwSupport#SyntaxOE](~/samples/snippets/csharp/VS_Snippets_Wpf/XAMLOvwSupport/CSharp/Page1.xaml#syntaxoe)]
The following example is object element syntax that also includes XAML content property syntax. The inner text contained within will be used to set the <xref:System.Windows.Controls.TextBox> XAML content property, <xref:System.Windows.Controls.TextBox.Text%2A>.
[!code-xaml[XAMLOvwSupport#ThisIsATextBox](~/samples/snippets/csharp/VS_Snippets_Wpf/XAMLOvwSupport/CSharp/Page1.xaml#thisisatextbox)]
### Content Models
A class might support a usage as a XAML object element in terms of the syntax, but that element will only function properly in an application or page when it is placed in an expected position of an overall content model or element tree. For example, a <xref:System.Windows.Controls.MenuItem> should typically only be placed as a child of a <xref:System.Windows.Controls.Primitives.MenuBase> derived class such as <xref:System.Windows.Controls.Menu>. Content models for specific elements are documented as part of the remarks on the class pages for controls and other WPF classes that can be used as XAML elements.
<a name="properties_of_object_elements"></a>
## Properties of Object Elements
Properties in XAML are set by a variety of possible syntaxes. Which syntax can be used for a particular property will vary, based on the underlying type system characteristics of the property that you are setting.
By setting values of properties, you add features or characteristics to objects as they exist in the run time object graph. The initial state of the created object from a object element is based on the parameterless constructor behavior. Typically, your application will use something other than a completely default instance of any given object.
<a name="attribute_syntax_properties"></a>
## Attribute Syntax (Properties)
Attribute syntax is the XAML markup syntax that sets a value for a property by declaring an attribute on an existing object element. The attribute name must match the CLR member name of the property of the class that backs the relevant object element. The attribute name is followed by an assignment operator (=). The attribute value must be a string enclosed within quotes.
### Content Models
@@ -232,10 +273,10 @@ The value of a XAML content property must be given either entirely before or ent
[!code-xaml[XAMLOvwSupport#SyntaxContent](~/samples/snippets/csharp/VS_Snippets_Wpf/XAMLOvwSupport/CSharp/page5.xaml#syntaxcontent)]
Note that neither the property element for <xref:System.Windows.Controls.Panel.Children%2A> nor the element for the <xref:System.Windows.Controls.UIElementCollection> is required in the markup. This is a design feature of XAML so that recursively contained elements that define a [!INCLUDE[TLA2#tla_ui](../../../includes/tla2sharptla-ui-md.md)] are more intuitively represented as a tree of nested elements with immediate parent-child element relationships, without intervening property element tags or collection objects. In fact, <xref:System.Windows.Controls.UIElementCollection> cannot be specified explicitly in markup as an object element, by design. Because its only intended use is as an implicit collection, <xref:System.Windows.Controls.UIElementCollection> does not expose a public parameterless constructor and thus cannot be instantiated as an object element.
Note that neither the property element for <xref:System.Windows.Controls.Panel.Children%2A> nor the element for the <xref:System.Windows.Controls.UIElementCollection> is required in the markup. This is a design feature of XAML so that recursively contained elements that define a UI are more intuitively represented as a tree of nested elements with immediate parent-child element relationships, without intervening property element tags or collection objects. In fact, <xref:System.Windows.Controls.UIElementCollection> cannot be specified explicitly in markup as an object element, by design. Because its only intended use is as an implicit collection, <xref:System.Windows.Controls.UIElementCollection> does not expose a public parameterless constructor and thus cannot be instantiated as an object element.
### Mixing Property Elements and Object Elements in an Object with a Content Property
The XAML specification declares that a XAML processor can enforce that object elements that are used to fill the XAML content property within an object element must be contiguous, and must not be mixed. This restriction against mixing property elements and content is enforced by the [!INCLUDE[TLA2#tla_winclient](../../../includes/tla2sharptla-winclient-md.md)] XAML processors.
The XAML specification declares that a XAML processor can enforce that object elements that are used to fill the XAML content property within an object element must be contiguous, and must not be mixed. This restriction against mixing property elements and content is enforced by the WPF XAML processors.
You can have a child object element as the first immediate markup within an object element. Then you can introduce property elements. Or, you can specify one or more property elements, then content, then more property elements. But once a property element follows content, you cannot introduce any further content, you can only add property elements.
@@ -243,7 +284,7 @@ The value of a XAML content property must be given either entirely before or ent
<a name="xaml_namespaces"></a>
## XAML Namespaces
None of the preceding syntax examples specified a XAML namespace other than the default XAML namespace. In typical [!INCLUDE[TLA2#tla_winclient](../../../includes/tla2sharptla-winclient-md.md)] applications, the default XAML namespace is specified to be the [!INCLUDE[TLA2#tla_winclient](../../../includes/tla2sharptla-winclient-md.md)] namespace. You can specify XAML namespaces other than the default XAML namespace and still use similar syntax. But then, anywhere where a class is named that is not accessible within the default XAML namespace, that class name must be preceded with the prefix of the XAML namespace as mapped to the corresponding CLR namespace. For example, `<custom:Example/>` is object element syntax to instantiate an instance of the `Example` class, where the CLR namespace containing that class (and possibly the external assembly information that contains backing types) was previously mapped to the `custom` prefix.
None of the preceding syntax examples specified a XAML namespace other than the default XAML namespace. In typical WPF applications, the default XAML namespace is specified to be the WPF namespace. You can specify XAML namespaces other than the default XAML namespace and still use similar syntax. But then, anywhere where a class is named that is not accessible within the default XAML namespace, that class name must be preceded with the prefix of the XAML namespace as mapped to the corresponding CLR namespace. For example, `<custom:Example/>` is object element syntax to instantiate an instance of the `Example` class, where the CLR namespace containing that class (and possibly the external assembly information that contains backing types) was previously mapped to the `custom` prefix.
For more information about XAML namespaces, see [XAML Namespaces and Namespace Mapping for WPF XAML](xaml-namespaces-and-namespace-mapping-for-wpf-xaml.md).
@@ -251,7 +292,7 @@ The value of a XAML content property must be given either entirely before or ent
## Markup Extensions
XAML defines a markup extension programming entity that enables an escape from the normal XAML processor handling of string attribute values or object elements, and defers the processing to a backing class. The character that identifies a markup extension to a XAML processor when using attribute syntax is the opening curly brace ({), followed by any character other than a closing curly brace (}). The first string following the opening curly brace must reference the class that provides the particular extension behavior, where the reference may omit the substring "Extension" if that substring is part of the true class name. Thereafter, a single space may appear, and then each succeeding character is used as input by the extension implementation, up until the closing curly brace is encountered.
The .NET XAML implementation uses the <xref:System.Windows.Markup.MarkupExtension> abstract class as the basis for all of the markup extensions supported by [!INCLUDE[TLA2#tla_winclient](../../../includes/tla2sharptla-winclient-md.md)] as well as other frameworks or technologies. The markup extensions that [!INCLUDE[TLA2#tla_winclient](../../../includes/tla2sharptla-winclient-md.md)] specifically implements are often intended to provide a means to reference other existing objects, or to make deferred references to objects that will be evaluated at run time. For example, a simple WPF data binding is accomplished by specifying the `{Binding}` markup extension in place of the value that a particular property would ordinarily take. Many of the WPF markup extensions enable an attribute syntax for properties where an attribute syntax would not otherwise be possible. For example, a <xref:System.Windows.Style> object is a relatively complex type that contains a nested series of objects and properties. Styles in WPF are typically defined as a resource in a <xref:System.Windows.ResourceDictionary>, and then referenced through one of the two WPF markup extensions that request a resource. The markup extension defers the evaluation of the property value to a resource lookup and enables providing the value of the <xref:System.Windows.FrameworkElement.Style%2A> property, taking type <xref:System.Windows.Style>, in attribute syntax as in the following example:
The .NET XAML implementation uses the <xref:System.Windows.Markup.MarkupExtension> abstract class as the basis for all of the markup extensions supported by WPF as well as other frameworks or technologies. The markup extensions that WPF specifically implements are often intended to provide a means to reference other existing objects, or to make deferred references to objects that will be evaluated at run time. For example, a simple WPF data binding is accomplished by specifying the `{Binding}` markup extension in place of the value that a particular property would ordinarily take. Many of the WPF markup extensions enable an attribute syntax for properties where an attribute syntax would not otherwise be possible. For example, a <xref:System.Windows.Style> object is a relatively complex type that contains a nested series of objects and properties. Styles in WPF are typically defined as a resource in a <xref:System.Windows.ResourceDictionary>, and then referenced through one of the two WPF markup extensions that request a resource. The markup extension defers the evaluation of the property value to a resource lookup and enables providing the value of the <xref:System.Windows.FrameworkElement.Style%2A> property, taking type <xref:System.Windows.Style>, in attribute syntax as in the following example:
`<Button Style="{StaticResource MyStyle}">My button</Button>`
@@ -280,7 +321,7 @@ The value of a XAML content property must be given either entirely before or ent
|||
|-|-|
|`<Page`|Opening object element of the root element|
|`xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"`|The default ([!INCLUDE[TLA2#tla_winclient](../../../includes/tla2sharptla-winclient-md.md)]) XAML namespace|
|`xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"`|The default (WPF) XAML namespace|
|`xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"`|The XAML language XAML namespace|
|`x:Class="ExampleNamespace.ExampleCode"`|The partial class declaration that connects markup to any code-behind defined for the partial class|
|`>`|End of object element for the root. Object is not closed yet because the element contains child elements|
@@ -16,12 +16,12 @@ This example shows how to use the methods in the <xref:System.Windows.Controls.C
## Example
The following example creates a <xref:System.Windows.Controls.Grid> element with a <xref:System.Windows.FrameworkElement.Name%2A> of `grid1`. The <xref:System.Windows.Controls.Grid> contains a <xref:System.Windows.Controls.StackPanel> that holds <xref:System.Windows.Controls.Button> elements, each controlled by a different collection method. When you click a <xref:System.Windows.Controls.Button>, it activates a method call in the code-behind file.
[!code-xaml[ColumnDefinitionsGrid#1](~/samples/snippets/csharp/VS_Snippets_Wpf/ColumnDefinitionsGrid/CSharp/Window1.xaml#1)]
:::code language="xaml" source="snippets/manipulate-columns-and-rows-by-using-columndefinitionscollections/csharp/Window1.xaml" id="Snippet1":::
This example defines a series of custom methods, each corresponding to a <xref:System.Windows.Controls.Primitives.ButtonBase.Click> event in the [!INCLUDE[TLA#tla_xaml](../../../includes/tlasharptla-xaml-md.md)] file. You can change the number of columns and rows in the <xref:System.Windows.Controls.Grid> in several ways, which includes adding or removing rows and columns; and counting the total number of rows and columns. To prevent <xref:System.ArgumentOutOfRangeException> and <xref:System.ArgumentException> exceptions, you can use the error-checking functionality that the <xref:System.Windows.Controls.ColumnDefinitionCollection.RemoveRange%2A> method provides.
[!code-csharp[ColumnDefinitionsGrid#2](~/samples/snippets/csharp/VS_Snippets_Wpf/ColumnDefinitionsGrid/CSharp/Window1.xaml.cs#2)]
[!code-vb[ColumnDefinitionsGrid#2](~/samples/snippets/visualbasic/VS_Snippets_Wpf/ColumnDefinitionsGrid/VisualBasic/Window1.xaml.vb#2)]
:::code language="csharp" source="snippets/manipulate-columns-and-rows-by-using-columndefinitionscollections/csharp/Window1.xaml.cs" id="Snippet2":::
:::code language="vb" source="snippets/manipulate-columns-and-rows-by-using-columndefinitionscollections/vb/Window1.xaml.vb" id="Snippet2":::
## See also
@@ -0,0 +1,54 @@
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="columndefinitions_grid.Window1"
Title="ColumnDefinitions Sample">
<Border BorderBrush="Black" Background="White" BorderThickness="2">
<!-- <Snippet1> -->
<DockPanel Margin="10,0,0,0">
<TextBlock FontSize="20" FontWeight="Bold" DockPanel.Dock="Top">Grid Column and Row Collections</TextBlock>
<TextBlock DockPanel.Dock="Top">Click any of the buttons below to invoke the associated methods and properties of ColumnDefinition and RowDefinition Collections.</TextBlock>
<Grid DockPanel.Dock="Top" HorizontalAlignment="Left" Name="grid1" ShowGridLines="true" Width="625" Height="400" Background="#b0e0e6">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Width="625" DockPanel.Dock="Top">
<Button Width="125" Click="addCol">Add Column</Button>
<Button Width="125" Click="addRow">Add Row</Button>
<Button Width="125" Click="clearCol">Clear All Columns</Button>
<Button Width="125" Click="clearRow">Clear All Rows</Button>
<Button Width="125" Click="removeCol">Remove One Column</Button>
</StackPanel>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Width="625" DockPanel.Dock="Top">
<Button Width="125" Click="removeRow">Remove One Row</Button>
<Button Width="125" Click="colCount">How Many Columns?</Button>
<Button Width="125" Click="rowCount">How Many Rows?</Button>
<Button Width="125" Click="rem5Col">Remove 5 Columns</Button>
<Button Width="125" Click="rem5Row">Remove 5 Rows</Button>
</StackPanel>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Width="625" DockPanel.Dock="Top">
<Button Width="125" Click="containsRow">Contains Row?</Button>
<Button Width="125" Click="containsCol">Contains Column?</Button>
<Button Width="125" Click="insertRowAt">Insert Row</Button>
<Button Width="125" Click="insertColAt">Insert Column</Button>
<Button Width="125" Click="colReadOnly">IsReadOnly?</Button>
</StackPanel>
<TextBlock DockPanel.Dock="Top" Name="tp1"/>
<TextBlock DockPanel.Dock="Top" Name="tp2"/>
<TextBlock DockPanel.Dock="Top" Name="tp3"/>
<TextBlock DockPanel.Dock="Top" Name="tp4"/>
<TextBlock DockPanel.Dock="Top" Name="tp5"/>
</DockPanel>
<!-- </Snippet1> -->
</Border>
</Window>
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
@@ -1,14 +1,19 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<PropertyGroup>
<AssemblyName>SDKSample</AssemblyName>
<TargetType>winexe</TargetType>
<Configuration Condition="'$(Configuration)'==''">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<OutputPath>bin\$(Configuration)\</OutputPath>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<ProductVersion>10.0.20821</ProductVersion>
<ProjectGuid>{4BDD3A99-C878-405A-9108-7C948EA50659}</ProjectGuid>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ItemGroup>
@@ -44,4 +49,7 @@
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
</Project>
@@ -1,14 +1,19 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<PropertyGroup>
<AssemblyName>SDKSample</AssemblyName>
<TargetType>winexe</TargetType>
<Configuration Condition="'$(Configuration)'==''">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<OutputPath>bin\$(Configuration)\</OutputPath>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}</ProjectTypeGuids>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<ProductVersion>10.0.20821</ProductVersion>
<ProjectGuid>{9CD74B47-FC44-43A0-B18E-FFF7B4EA3EF8}</ProjectGuid>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
<ItemGroup>
@@ -39,4 +44,7 @@
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
</Project>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.diagnostics>
<sources>
<!-- This section defines the logging configuration for My.Application.Log -->
<source name="DefaultSource" switchName="DefaultSwitch">
<listeners>
<add name="FileLog"/>
<!-- Uncomment the below section to write to the Application Event Log -->
<!--<add name="EventLog"/>-->
</listeners>
</source>
</sources>
<switches>
<add name="DefaultSwitch" value="Information"/>
</switches>
<sharedListeners>
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
</sharedListeners>
</system.diagnostics>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
@@ -1,54 +0,0 @@
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="columndefinitions_grid.Window1"
Title="ColumnDefinitions Sample">
<Border BorderBrush="Black" Background="White" BorderThickness="2">
<DockPanel Margin="10,0,0,0">
<TextBlock FontSize="20" FontWeight="Bold" DockPanel.Dock="Top">Grid Column and Row Collections</TextBlock>
<TextBlock DockPanel.Dock="Top">Click any of the buttons below to invoke the associated methods and properties of ColumnDefinition and RowDefinition Collections.</TextBlock>
<!-- <Snippet1> -->
<Grid DockPanel.Dock="Top" HorizontalAlignment="Left" Name="grid1" ShowGridLines="true" Width="625" Height="400" Background="#b0e0e6">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Width="625" DockPanel.Dock="Top">
<Button Width="125" Click="addCol">Add Column</Button>
<Button Width="125" Click="addRow">Add Row</Button>
<Button Width="125" Click="clearCol">Clear All Columns</Button>
<Button Width="125" Click="clearRow">Clear All Rows</Button>
<Button Width="125" Click="removeCol">Remove One Column</Button>
</StackPanel>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Width="625" DockPanel.Dock="Top">
<Button Width="125" Click="removeRow">Remove One Row</Button>
<Button Width="125" Click="colCount">How Many Columns?</Button>
<Button Width="125" Click="rowCount">How Many Rows?</Button>
<Button Width="125" Click="rem5Col">Remove 5 Columns</Button>
<Button Width="125" Click="rem5Row">Remove 5 Rows</Button>
</StackPanel>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Width="625" DockPanel.Dock="Top">
<Button Width="125" Click="containsRow">Contains Row?</Button>
<Button Width="125" Click="containsCol">Contains Column?</Button>
<Button Width="125" Click="insertRowAt">Insert Row</Button>
<Button Width="125" Click="insertColAt">Insert Column</Button>
<Button Width="125" Click="colReadOnly">IsReadOnly?</Button>
</StackPanel>
<!-- </Snippet1> -->
<TextBlock DockPanel.Dock="Top" Name="tp1"/>
<TextBlock DockPanel.Dock="Top" Name="tp2"/>
<TextBlock DockPanel.Dock="Top" Name="tp3"/>
<TextBlock DockPanel.Dock="Top" Name="tp4"/>
<TextBlock DockPanel.Dock="Top" Name="tp5"/>
</DockPanel>
</Border>
</Window>