Computing: DOS, OS/2 & Windows Programming

Developing .NET desktop applications (in Visual Studio).

In my tutorial Introduction to developing .NET applications, I describe how to install the .NET SDK, and how to create .NET Console applications in C#, VB.NET and F#, using the SDK command line interface (CLI). This article may be seen as a continuation of that tutorial, thus it is supposed that you have the SDK installed on your computer, and that you know how to use dotnet.exe to create, build, run and publish a .NET project.

This tutorial is about the creation of desktop applications (i.e. applications with a graphical user interface running on the local computer) using .NET. We will start with creating a WinForms project (in C#) using the SDK CLI, then, for the rest of the tutorial (WinForms projects in C# and VB.NET; WPF application in C#), we will switch to Visual Studio, a rapid development IDE that allows to create the application GUI by simple drag-and-drop, and to define the GUI layout by simply setting the form components' properties, entering values into their Property sheet. All tutorial samples have been built and tested on Windows 11; the tutorial should apply to Windows 10, too.

Creating a WinForms project using the SDK CLI.

Windows Forms .NET (WinForms) are a UI framework that creates rich desktop client apps for Windows. The Windows Forms development platform supports a broad set of app development features, including controls, graphics, data binding, and user input. Windows Forms features a drag-and-drop visual designer in Visual Studio to easily create Windows Forms apps. There are two implementations of Windows Forms:

Important to be aware, that independently of the Windows Forms implementation that you choose for building your application, these apps are exclusively intended for MS Windows, thus no possibility to port them to macOS, or Linux (it may be possible to run them on Linux using Wine...).

To create a .NET WinForms project, called "HelloWorld", cd to the directory where you want to create the project (I use C:\Data\Programming\dotNET), and run the following command:
    dotnet new winforms -o HelloWorld

The screenshot shows the output of dotnet.exe.

.NET development on Windows 11: .NET SDK CLI - Creating a WinForms project using C#

This will create a project folder with same name as the project and containing several files. Among these (in the project folder itself), you find three C# source files, called respectively Program.cs, Form1.cs, and Form1.Designer.cs.

.NET development on Windows 11: .NET SDK CLI - Project directory of a C# WinForms application

The file Program.cs contains the code to initialize and start the application. Similar to the .lpr file in Lazarus, all of its code is generated automatically, and we can just let it as it is.

The file Form1.Designer.cs contains the code concerning the form (that will become the application's GUI, i.e. the window, where the application is running in) layout. The screenshot below shows this file opened in Notepad++. You can safely ignore the first part of the file content (and do not modify it!). It's up from the private void InitializeComponent() declaration, that starts the code that we have to deal with. In this rudimentary application, generated by dotnet.exe, and that does nothing more and nothing less than displaying an empty window, the code consists of defining a form with a width of 800 pixels, and a height of 450 pixels, the Text property (that will become the application window's title) being set to "Form1".

.NET development on Windows 11: Content of the file 'Form1.Designer.cs' of a C# WinForms application skeleton

Note, that from the point of view OO, all methods and properties are part of a class called "Form1", defined in a namespace called "HelloWorld" (the name that we gave to the project). Thus, all three C# files will start with a namespace HelloWorld; instruction.

It's in the file Form1.cs that we will define the methods of the "Form1" class. At this stage, this file contains just the following:
    namespace HelloWorld;
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }

Note: Instead of creating a .NET project (created and built with the SDK CLI tools), we could also create a simple C# program (built with the C# compiler). In that case, we would have a single C# source file, containing everything needed to build the executable. If you are interested in this possibility, have a look into a C# manual.

The files generated by dotnet.exe are a rudimentary, but ready to run application, that we can build using the command dotnet build. The screenshot shows the files and folders created by the build process.

.NET development on Windows 11: .NET SDK CLI - Files and folders created by the build of a C# WinForms application

We can run the executable created either using the dotnet run command, or by directly double-clicking it in Windows File Explorer. The result is an empty window with window title "Form1".

Our "HelloWorld" application should be very simple: A form with nothing than a button labeled "Click me", and pushing this button make pop up a message box displaying the "Hello World" message.

To make the button (I called it "btAdd") a member of the "Form1" class, we declare it as being of type "Button" by the following statement to insert into the file Form1.Designer.cs (where we can put it at the end of the partial class Form1 declaration):
    private System.Windows.Forms.Button btHello;

The creation of the button has to be part of the InitializeComponent() method, itself part of the declaration partial class Form1 in Form1.Designer.cs. It is done by the following statement (that we can put as first instruction of the method).
    this.btHello = new System.Windows.Forms.Button();

Following this instruction, we can define the button's properties: location on the form, size, caption, and (as we need to reference it in the button's "Click" method, also a name (?). After these, we then have the original code, that creates the form, where we should change the form's size (I chose 200×200 pixels); we can also give a more appropriate value to the form's Text property (= window title), for example "Hello".

This is not all: We have to add the button to the form's controls. This is done at the end of the the InitializeComponent() method, using the instruction
    this.Controls.Add(this.btHello);

Here is the code of the file Form1.Designer.cs, after having done the modification, as described above:
    namespace HelloWorld;
    partial class Form1
    {
        private System.ComponentModel.IContainer components = null;
        protected override void Dispose(bool disposing)
        {
            ...
        }
        private void InitializeComponent()
        {
            this.btHello = new System.Windows.Forms.Button();
            this.btHello.Name = "btHello";
            this.btHello.Location = new System.Drawing.Point(60, 70);
            this.btHello.Size = new System.Drawing.Size(80, 30);
            this.btHello.Text = "Click me";
            this.components = new System.ComponentModel.Container();
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(200, 200);
            this.Text = "Hello";
            this.Controls.Add(this.btHello);
        }
        private System.Windows.Forms.Button btHello;
    }

Finally, we have to create a "Click" event for the button. This is done using the following instruction (that we put after the button's properties settings):
    this.btHello.Click += new System.EventHandler(this.btHello_Click);

The corresponding method btHello_Click has to be added to the file Form1.cs. As I said above, pushing the button should make pop up a message box. Here's the content of the C# file:
    namespace HelloWorld;
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void btHello_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hello .NET World!");
        }
    }

We can now build and run the application. The screenshot shows these operations in Windows Command Prompt, as well as the "HelloWorld" application window, and the dialog box displayed after I had pushed the button (to note that the position of the application window and the dialog box are not those where these effectively appear; in fact, I moved them in order to get the screenshot as shown below).

.NET development on Windows 11: .NET SDK CLI - Build and execution of a C# WinForms application

We can publish the application, running the command dotnet publish from the project directory. The files, that have to be included into the distribution are placed in the directory HelloWorld\bin\Release\net9.0-windows\publish. With .NET Core 9.0 installed on my Windows 10 laptop, the application may be run there without any issue (just double-clicking the .exe file in Windows File Explorer).

Creating a WinForms project using Visual Studio.

The SDK CLI tools may be sufficient if you are developing Console applications, but for desktop applications with a graphical user interface, you would probably prefer an IDE that includes rapid development (RAD) features, such creating the form layout by simply dragging visual components to the location where you want to place them, and define the properties of the components by filling their values into the component's Property sheet, rather that to have to write the code. There are several IDEs that you may use to develop .NET applications. On my Windows 11, I actually use Visual Studio 2022. The Community Edition of this software by Microsoft is free of charge and includes everything that you could need to create whatever kind of application based on .NET Framework or .NET Core. If you need help to install Visual Studio, my article Installing Visual Studio 2022 on Windows 11 may be helpful.

Creating a WinForms C# project.

On the Visual Studio entry page, choose Create a new project. The possible project types available depend on the Visual Studio components that you did actually install. Normally the list of project types is very long; you can limit the display by language, platform and target. For our WinForms C# project, you can, for example, set the language to "C#", and the target to "Desktop". Among the remaining project types, I chose Windows Forms App (.NET Framework).

.NET development on Windows 11: Visual Studio - Creating a WinForms C# project [1]

The configuration of the project essentially consists in giving it a name and choosing a project directory. To note, that Visual Studio allows to group several projects as a so called solution. Normally, your project is the solution, thus the checkbox Place the solution and the project in the same directory should be selected. By default, Visual Studio solutions are created in the directory C:\Users\<user-name>\source\repos. The name of the solution folder will be the one that we give to the project on this page (I named my solution "NamesList"). To note, that this will also be the name of the executable created by the build.

Another configuration option that we must choose here is the .NET version. With the project type that we selected, it will be the Windows-specific .NET Framework (not .NET Core) that will be used. The default version is .NET Framework 4.7.2 (the runtime of which is included in all Window 10/11 releases by default, I think). Other choices are the newer Framework 4.8, as well as the old and even very old versions.

The screenshot shows the configuration of my "NamesList" project.

.NET development on Windows 11: Visual Studio - Creating a WinForms C# project [2]

The Visual Studio IDE is easy to use. All we need is grouped in one window (as a difference with these modern IDEs, as for example VSCode, with their different views to be selected in the left pane): The top-left pane shows the form layout, either in Design view, or in Code view (you can choose the view by selecting the corresponding item from the View menu); the bottom-left pane shows the messages (syntax errors, build output...); the top-right pane shows the Solution Explorer; and the bottom-right pane shows the Property sheet of the component selected (either the form itself, or one of its controls). If you are used to work with Lazarus (RAD for Free Pascal), you'll be comfortable with Visual Studio at once.

.NET development on Windows 11: Visual Studio - Creating a WinForms C# project [3]

The files generated when creating the project are the same as when using dotnet.exe; in particular there are the 3 C# source files Program.cs, Form1.cs and Form1.Design.cs. As a difference with using the SDK CLI, we have not to really care about what is placed in which file. Except for the program logic (that we'll have, of course, to manually enter into the editor), code generation will be mostly automatic. We create the form layout by dragging visual components onto the form, and setting their properties in the Property sheet. The events, associated with a given control, can be selected in a similar way, and Visual Studio will automatically generate the corresponding method declaration. Really easy, as you will see in the following paragraphs.

The visual components are included in the so-called Toolbox (that's a difference with Lazarus, where they can be accessed on the components bar). To display the toolbox, select the corresponding item from the View menu.

.NET development on Windows 11: Visual Studio - Using the Toolbox visual components to create the form layout

The project, that I describe here, is an example listed in the official WinForms documentation by Microsoft. A textbox (that's what in Lazarus is called an edit field) to enter a name, and a button that is used to add the name to a listbox. There should also be a label, with caption "Names", above the listbox.

We create these 4 components by dragging an item from the toolbox onto the form. Then, with a given component selected, we can change its properties in the Property sheet (the location of a control can also be changed be simply dragging it to its new position; its size can also be changed by dragging its resize handles).

On the screenshot below, the 4 components are already created. The label is selected, and in its Property sheet, I have selected the Text property (in Lazarus, this property is called Caption) to change it to "Names".

.NET development on Windows 11: WinForms C# project in Visual Studio - Form components and their properties

To pass from the layout on the screenshot above to the one on the screenshot below, I made several changes to the layout: resizing the form, arranging the 4 components on the form (Location property), resizing them (Size property), changing the font size, changing the caption of the button (Text property) to "Add", ...

I also changed the Name property of those components that are used in the program logic code. I called the textbox "edName", the listbox "lbNames", and the button "btAdd".

On the screenshot below, these changes have been applied. With the button selected, I changed from the display of the Property sheet to the display of the Events sheet (this is done by clicking the yellow "flash" icon). Here, we can associate a given control with a given event by simply clicking the event name. As pushing the button corresponds to a Click event associated with the Button control, we have to select the item "Click" from the Events sheet list.

.NET development on Windows 11: WinForms C# project in Visual Studio - Associating a button with a 'Click' event

This automatically opens the file Form1.cs in the editor, showing the method, corresponding to the event, the method's declaration having been generated by Visual Studio.

.NET development on Windows 11: WinForms C# project in Visual Studio - Automatically generated 'Click' event method declaration

The program logic of the method should add the name entered into the textbox to the listbox items. This action should only be taken if the textbox isn't empty; also we only want each name once in the list. Here is the C# code:
    private void btAdd_Click(object sender, EventArgs e)
    {
        if (!string.IsNullOrWhiteSpace(edName.Text) && !lbNames.Items.Contains(edName.Text))
            lbNames.Items.Add(edName.Text);
    }

To build the application, choose Build > Build solution from the menu. The screenshot shows the output of the successful build.

.NET development on Windows 11: WinForms C# project in Visual Studio - Building the solution

The executable, called NamesList.exe will be created, together with other files required to run it, in the directory NamesList\bin\Debug or NamesList\bin\Release, depending on the build method selected in Visual Studio. We can run it either from within the IDE (use one of the two "triangles" in the icons bar, the first being to debug, the second to run without debugging), or by double-clicking it in File Explorer.

.NET development on Windows 11: WinForms C# project in Visual Studio - Running the executable

Creating a WinForms VB.NET project.

The screenshot shows the selection of the Windows Forms App (.NET Framework) project type for VB.NET.

.NET development on Windows 11: Visual Studio - Creating a WinForms VB.NET project

I named my project "Equation" and, as before, chose to build it using .NET Framework 4.7.2.

This program sample actually is a "real" application, that may be used to solve second degree in one variable equations (without calculation of the complex roots). Click the following link if you would like to download the source code.

Creating a Visual Basic WinForms application is essentially the same as creating a C# WinForms application, so I will not repeat the details. To note, that with Visual Basic there are only two source files created in the project directory: Form1.vb and Form1.Designer.vb.

The user interface of the application is quite simple: three textboxes to enter the equation's coefficients, three textboxes for the output of the calculation (one indicating the type of solution, the other two to display the roots if they exist, or more exactly if they are real numbers), and a button to launch the calculation.

The screenshot below has been taken when the design of the form was finished and I had built and run the application to check if the GUI looks like I expected. At this stage, I have selected the "Solve" button and the next step will be to select the "Click" event to be associated with the button to be pushed.

.NET development on Windows 11: WinForms VB.NET project in Visual Studio - Associating a button with a 'Click' event

Selecting the "Click" event from the button's Event sheet will automatically open the file Form1.vb in the editor, showing the method corresponding to the event, the method's declaration having been generated by Visual Studio.

.NET development on Windows 11: WinForms VB.NET project in Visual Studio - Automatically generated 'Click' event method declaration

Here is the Visual Basic code of my 2nd degree equation solver application:
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim a, b, c, delta As Single
        Dim solution As String
        edX1.Text = ""
        edX2.Text = ""
        edSolution.Text = ""
        If edA.Text <> "" And edB.Text <> "" And edC.Text <> "" Then
            a = CSng(edA.Text)
            b = CSng(edB.Text)
            c = CSng(edC.Text)
            If a = 0 Then
                MessageBox.Show("This is a 1st degree equation...")
                If b = 0 Then
                    If c = 0 Then
                        solution = "Infinity of solutions"
                    Else
                        solution = "No solution"
                    End If
                Else
                    solution = "One unique solution"
                    edX1.Text = Math.Round(1000 * (-c / b)) / 1000
                End If
            Else
                delta = b * b - 4 * a * c
                If delta < 0 Then
                    solution = "No real solution(s)"
                ElseIf delta = 0 Then
                    solution = "One double solution"
                    edX1.Text = Math.Round(1000 * (-b / (2 * a))) / 1000
                Else
                    solution = "Two unique solutions"
                    edX1.Text = Math.Round(1000 * ((-b + Math.Sqrt(delta)) / (2 * a))) / 1000
                    edX2.Text = Math.Round(1000 * ((-b - Math.Sqrt(delta)) / (2 * a))) / 1000
                End If
            End If
            edSolution.Text = solution
        Else
            MessageBox.Show("Missing coefficient(s)!")
        End If
    End Sub

The screenshot shows an execution of the application from within Visual Studio.

.NET development on Windows 11: WinForms VB.NET project in Visual Studio - Running the executable

Creating a WPF project using Visual Studio.

Windows Presentation Foundation (WPF) is a UI framework that is resolution-independent and uses a vector-based rendering engine, built to take advantage of modern graphics hardware. WPF provides a comprehensive set of application-development features that include Extensible Application Markup Language (XAML), controls, data binding, layout, 2D and 3D graphics, animation, styles, templates, documents, media, text, and typography. WPF is part of .NET, so you can build applications that incorporate other elements of the .NET API.

There are two implementations of WPF:

Important to be aware, that independently of the WPF implementation that you choose for building your application, these apps are exclusively intended for MS Windows, thus no possibility to port them to macOS, or Linux.

WPF lets you develop an application using both markup and code-behind. You normally use XAML to implement the appearance of an application, while using managed programming languages (code-behind) to implement its behavior (separation of appearance and behavior).

XAML is an XML-based markup language that implements an application's appearance declaratively. You typically use it to define the application's windows and their components (controls, dialog boxes, shapes, graphics). Here is a typical XAML declaration of an application's window:
    <Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        Title="Window title"
        Width="250" Height="100">
    </Window>

The window and its components are defined as elements (ex: <Window>); they are configured using attributes (ex: Title is an attribute that may be used with the <Window> element). At run time, WPF converts the elements and attributes that are defined in XAML to instances of WPF classes.

The main behavior of an application is to implement the functionality that responds to user interactions (response to an event, as for example pushing a button). In WPF, this behavior is implemented in code that is associated with the XAML markup (code-behind). To make this possible, the XAML declaration of the application's window has to be changed as follows:
    <Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="MyWPFProject.MainWindow"
        Title="Window title"
        Width="250" Height="100">
    </Window>

The updated markup defines the xmlns:x namespace and maps it to the schema that adds support for the code-behind types. The x:Class attribute is used to associate a code-behind class to a specific XAML markup. Considering that this attribute is declared on the <Window> element, the code-behind class must inherit from the Window class. This leads to the following skeleton of the C# file containing the code behind:
    using System.Windows;
    namespace MyWPFProject
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
        }
    }
When developing with Visual Studio, the namespace will be named using the name that we specify when creating the project.

Note: The explanations in the preceding paragraphs are from the official Microsoft WPF documentation...

Creating a WPF C# project.

On the Visual Studio entry page, choose Create a new project. With C# selected as language, choose WPF Application as project type.

.NET development on Windows 11: Visual Studio - Creating a WPF C# project [1]

On the following two pages, I named my project "NamesList2" and choose to build it using .NET 8.0.

The Visual Studio IDE window is subdivided as follows: The top-left pane shows the XAML designer; the middle-left pane shows the XAML code editor; the bottom-left pane shows the messages. As with WinForms, the top-right pane shows the Solution Explorer, and the bottom-right pane shows the Property sheet of the component selected (either the form itself, or one of its controls). Eventually, the Toolbox window is also open.

.NET development on Windows 11: Visual Studio - Creating a WPF C# project [2]

As WPF project sample for this part of the tutorial, I chose the names list example from the official Microsoft WPF documentation (it actually is the same application that the one, we built before using WinForms). It is possible to create the form layout by drag-and-drop, but you can also do it by editing the XAML code. It's this second way that is described in the following paragraphs; a good occasion to learn about XAML, and how its layout controls help to place and to size child controls in exactly the way that we want.

If you have a look into the project directory, you see several .xaml and .cs files. The two most important for us are MainWindow.xaml, the XAML window layout (file opened in the bottom-left pane of the IDE), and MainWindow.xaml.cs the C# file containing the "code behind".

Before starting with placing the different controls, lets resize the application window: In the declaration of the <Window> element, set the Width attribute to "260", and the Height attribute to "180". Also, lets set the Title attribute to "Names List",

The easiest way to create a precise layout is to use the Grid layout control. A Grid is much like a table, with rows and columns (with numbering starting at 0). A given row-column combination defines a given cell, corresponding to a given location within the application's window.

The screenshot below shows the file MainWindow.xaml, where I have modified the <Window> element as described above. The one row and one column <Grid> element has been added automatically by Visual Studio as default layout control.

.NET development on Windows 11: Visual Studio - Creating a WPF C# project [3]

Lets change the grid by first applying a margin of 10 pixels, and second defining 2 rows and 2 columns. Here is the corresponding XAML code:
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
    </Grid>

The screenshot shows how making these changes in the XAML Code Editor affects the display in the XAML Designer. Note, that I applied a zooming factor of 200% to make the display of the window in the designer bigger.

.NET development on Windows 11: WPF C# project in Visual Studio - Custom 'Grid' layout control

The application GUI will be the same as for our WinForms application, thus we'll have to place 4 components onto the grid: a label, a listbox, a textbox, and a button. Lets start with the label. We add it to the window, by adding the following line after the closing tag of the grid column definitions:
        <Label>Names</Label>

This places the label with caption "Names" into cell (0, 0) of the grid (upper-left cell). The reason why it is placed there is because this declaration is the short form of
        <Label Grid.Row="0" Grid.Column="0">Names</Label>

The label will occupy the whole width and whole height of the cell. This is because of the usage of the asterisk in the row height resp. column width definitions. For the width this is so far ok, but we don't want the label to be as high. There is a simple mean to set it to its default height: Replace the asterisk in the first row height definition by Auto.

Here is the XAML code, with a label of correct height added to the window:
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Label>Names</Label>
    </Grid>

The screenshots below show the window design after addition of the <Label> element to the XAML file. The screenshot on the left has been taken before, the screenshot on the right after the first row height has been changed from "*" to "Auto".

.NET development on Windows 11: WPF C# project in Visual Studio 'Label' control [1]
.NET development on Windows 11: WPF C# project in Visual Studio 'Label' control [2]

Now, lets define the other 3 components, placing the listbox in cell (1, 0), the textbox in cell (0, 1) and the button in cell (1, 1):
        <Label>Names</Label>
        <ListBox Grid.Row="1" x:Name="lbNames"/>
        <TextBox Grid.Column="1" Grid.Row="0" x:Name="edName" />
        <Button Grid.Column="1" Grid.Row="1" x:Name="btAdd">Add</Button>

Note the special attribute x:Name that I use with all three elements. This attribute is used to give the components a name that we can use to reference it in the "code behind". Concerning the button, it will have its caption set to "Add".

The screenshot shows the window design after the 4 elements have been added to the XAML file. Note that the button entirely fills the cell (1, 1), that in particular its height equals the height of the cell (because the height of the second row is set to "*").

.NET development on Windows 11: WPF C# project in Visual Studio - 'Grid' control with 4 child-controls

As the height of the second row cells has to be the one of the listbox, it's the height of the button that we'll have to change. We can do this by selecting it in the Design window, and then, in its Property sheet, setting its Height property to 25, for example. This is not yet what we want. In fact, all components are centered within their grid-cell, so we have to change its Vertical Alignment property to "Top".

The screenshot shows button with its height of 25 pixels aligned at the middle of the grid cell (1, 1). You can also see how I clicked the "Top" icon in the Property sheet to align the button vertically with the top of the cell.

.NET development on Windows 11: WPF C# project in Visual Studio - Height and alignment of a 'Button' control

Another change to the layout, that we can do here, is to add a left margin of, for example 10 pixels, for the button (to keep the button and the textbox aligned, this has to be done for the textbox, too), in order to create some space between itself and the listbox.

The screenshot shows the execution of the application (that is not yet functional at this stage). Building and running it was just to check what the application window looks like.

.NET development on Windows 11: WPF C# project in Visual Studio - Testing the window layout

The window layout is not bad (that the listbox is located nearer to the top than the button is due to the fact that I added a top margin to the button, but forgot to add it to the listbox, too). But, wouldn't it be nicer if the textbox was aligned with the listbox rather than with the label, as it actually is the case in our WinForms application?

This means that the textbox has to be placed in grid cell (1, 1), what obviously is a problem, as the button already occupies this cell. I suppose that there are several ways to solve this problem. In the names list example in the Microsoft WPF documentation, on which this part of the tutorial is based on, they solve the issue by using a Stack panel. The Stack panel is a layout control, that differs from the Grid in how the controls are placed. While you tell the Grid where you want the controls to be with the Grid.Row and Grid.Column attached properties, the Stack panel works automatically by placing the first control, then placing the next control after it, continuing until all controls have been placed. It "stacks" each control below the other. Another difference is that a control placed into a Grid cell by default fills up the entire cell, whereas a control, placed into a Stack panel by default fills its width, but as height uses the default height of the control.

Here is the new code for the positioning of the label, the listbox, the textbox and the button within the Grid:
        <Label>Names</Label>
        <ListBox Grid.Row="1" x:Name="lbNames"/>
        <StackPanel Grid.Row="1" Grid.Column="1" Margin="10,0,0,0">
            <TextBox x:Name="edName" />
            <Button x:Name="btAdd" Margin="0,5,0,0">Add</Button>
        </StackPanel>

If you look at the code, you can see, that I added a left margin of 10 pixels to the Stack panel (space between the list box and the controls within the Stack panel), and a top margin of 5 pixels to the button (vertical separation from the text box). The values specified for the Margin attribute actually are "left, top, right, bottom".

The screenshot shows the window design after these changes have been applied.

.NET development on Windows 11: WPF C# project in Visual Studio - Usage of a 'Stack panel' to place several controls into a 'Grid' cell

Our application should add the name entered by the user into the text box to the listbox, when the button is pushed. Thus, we'll have to associate the button with a Click event, the code that adds the name to the listbox having to be part of the corresponding method. Apart from the code itself, all this may be generated by Visual Studio. Select the button, and in the bottom-right pane, switch from the Properties sheet to the Events sheet. All you have to do is to click in the field at the right of the Click item of the Events sheet.

This opens the file MainWindow.xaml.cs in the editor, with the method declaration generated. Looking at the content of MainWindow.xaml again, we can see that in XAML, the Click event is implemented by a Click attribute, the button relative line now being like this:
            <Button x:Name="btAdd" Margin="0,5,0,0" Click="btAdd_Click">Add</Button>

The screenshot shows how this looks like in Visual Studio.

.NET development on Windows 11: WPF C# project in Visual Studio - Adding a 'Click' event to a 'Button' control

All that remains to do is to add the "code behind" to the btAdd_Click method. Here is the content of my MainWindow.xaml.cs:
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Xml.Linq;
    namespace NamesList2
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
            private void btAdd_Click(object sender, RoutedEventArgs e)
            {
                if (!string.IsNullOrWhiteSpace(edName.Text) && !lbNames.Items.Contains(edName.Text))
                {
                    lbNames.Items.Add(edName.Text);
                    edName.Clear();
                }
            }

        }
    }

And to be complete, here is the final content of MainWindow.xaml:
    <Window x:Class="NamesList2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NamesList2"
        mc:Ignorable="d"
        Title="Names List" Height="180" Width="260">
        <Grid Margin="10">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Label>Names</Label>
            <ListBox Grid.Row="1" x:Name="lbNames"/>
            <StackPanel Grid.Row="1" Grid.Column="1" Margin="10,0,0,0">
                <TextBox x:Name="edName" />
                <Button x:Name="btAdd" Margin="0,5,0,0" Click="btAdd_Click">Add</Button>
            </StackPanel>
        </Grid>
    </Window>

The screenshot shows the execution of NamesList2.exe on my Windows 10 laptop.

.NET development on Windows 11: Running the application on Windows 10

Publishing a Visual Studio project.

In most cases, deploying the files created by a Visual Studio Release build is sufficient to run a WinForms or WPF application on another computer. In the case of a WinForms project, these files are located in <project-directory>\bin\Release; in the case of a WPF project (for example build with .NET 8.0), they are located in <project-directory>\bin\Release\net8.0-windows.

The proper way to publish a Visual Studio desktop project is to use the Publish <project-name> command from the Build menu. This will deploy your project using the so-called ClickOnce technology. "ClickOnce is a deployment technology that allows you to create self-updating Windows-based applications with minimal user interaction. It simplifies the deployment process by providing an easy way to install, run, and update your application on end-user computers. With ClickOnce, you can overcome common deployment challenges, such as difficulties in updating applications, impact to the user’s computer, and security permissions.", they write in the article Deploying a Windows Forms Application Using ClickOnce: A Comprehensive Guide at medium.com.

A detailed description of ClickOnce deployment is outside the scope of this tutorial. Here are the basics: By default the files to be published are generated in the directory <project-directory>\Publish, that will contain the program setup.exe, a manifest file and a folder with the application files. The program setup.exe is intended for a silent install of the application on the end-users computer. It does the following: 1. copy the application files to some local directory; 2. create a shortcut in the Windows Start menu, to run the application; 3. create an item in Programs and Features (Add/Remove Programs) of Control Panel to uninstall the application.

When creating the content of the publish folder in Visual Studio, you are asked from where the end-user will install the application (web site, network share, or CD/DVD), and if the application should or not auto-update. For details, cf. the article mentioned above, or have a look at the Microsoft documentation.

As mentioned in the article, the ClickOnce deployment has the following advantages:

The only issue with this deployment method is that if the application is not signed by a verified publisher, a warning message box will pop up when the end-user starts the installation process. If you intend to deploy your applications in the "real world", or if this bothers you, please, search the Internet for help...

The screenshot below was taken when I installed the NamesList project of the tutorial on my Windows 10 laptop, with the Publisher cannot be verified security warning pop-up, when I launched the installation.

.NET development on Windows 11: Project publishing using ClickOnce - Security warning on the end-user Windows 10 machine

What's next?

If you are serious about .NET development, you should visit the Microsoft website, where you can view and download as PDF the documentation concerning the development of WinForms and WPF desktop applications. There is also lots of documentation concerning .NET, Visual Studio, C#, and Visual Basic available.

On my site, the .NET tutorial will (one day) be continued by a third part: Developing ASP.NET web applications (in Visual Studio).


If you find this text helpful, please, support me and this website by signing my guestbook.