Create, run and change your first WPF app: a small greeting window with a text box and a button, built step by step with XAML and a few lines of C#.

Bishal Biswas
Self Learner
What you will build
In this lesson you create a real WPF app from scratch. It is small on purpose: a window that asks for your name and says hello when you click a button.
+----------------------------------+
| Greeter _ [] X|
|----------------------------------|
| What is your name? |
| [ Bishal ] |
| [ Say hello ] |
| |
| Hello, Bishal! Welcome to WPF. |
+----------------------------------+
Along the way you will see the full loop every WPF developer goes through: create a project, describe the window in XAML, react to a click in C#, and run the app. Make sure you have finished Setting Up Visual Studio and the .NET SDK first.
Step 1: Create the project
With the command line
Open a terminal in your code folder and run:
dotnet new wpf -n Greeter
cd Greeter
This creates a folder called Greeter with a ready to run WPF app inside.
With Visual Studio
- Choose Create a new project.
- Search for WPF Application and pick the C# one. (Avoid “WPF App (.NET Framework)”, which is the old Windows only .NET.)
- Name it
Greeterand click Next. - Pick .NET 10.0 (Long Term Support) and click Create.
Both ways give you the same files. You will look at each one in Understanding the Project Structure. For now, you only care about two of them: MainWindow.xaml and MainWindow.xaml.cs.
Step 2: Run the empty app
Before changing anything, run it once:
dotnet run
In Visual Studio, press F5. An empty window titled MainWindow opens. It already has a title bar, can be moved, resized, minimised and closed. WPF gives you all of that for free.
Close the window to stop the app.
Step 3: Look at the starting XAML
Open MainWindow.xaml. It looks like this:
<Window x:Class="Greeter.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:Greeter"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
</Grid>
</Window>
The xmlns lines at the top are namespaces. They tell WPF where to find words like Window and Grid. Leave them alone for now. They are explained in XAML Namespaces and Markup Extensions.
The parts that matter today:
Title="MainWindow"is the text in the title bar.Height="450" Width="800"is the starting size.Gridis an empty layout panel. Whatever you put inside it appears in the window.
Step 4: Change the title and size
Change the last line of the Window tag so it reads:
Title="Greeter" Height="260" Width="400">
Run the app again. The window is smaller and the title bar says Greeter. You just changed your app by editing XAML.
Step 5: Add controls
Now replace the empty Grid with this:
<StackPanel Margin="20">
<TextBlock Text="What is your name?" FontSize="16" />
<TextBox x:Name="NameBox" Margin="0,8,0,0" />
<Button Content="Say hello" Margin="0,12,0,0"
HorizontalAlignment="Left" Padding="12,4" />
<TextBlock x:Name="GreetingText" Margin="0,16,0,0" FontSize="16" />
</StackPanel>
Here is what each piece does:
StackPanelarranges its children in a column, one below the other.Margin="20"adds 20 units of space around it, so nothing touches the window edge.TextBlockshows read only text.TextBoxis a box the user can type in.Buttonis a clickable button.Contentis the text on it.Margin="0,8,0,0"means left 0, top 8, right 0, bottom 0. It pushes the control down a little.x:Name="NameBox"gives the control a name, so your C# code can talk to it.
Run the app. You can type in the box and click the button, but nothing happens yet. That is the next step.
Step 6: Handle the click
A click handler is a C# method that runs when the user clicks a button. First, tell the button which method to call by adding a Click attribute:
<Button Content="Say hello" Margin="0,12,0,0"
HorizontalAlignment="Left" Padding="12,4"
Click="SayHello_Click" />
Now open MainWindow.xaml.cs. This is the code-behind file: the C# class that belongs to the window. Add a method below the constructor:
private void SayHello_Click(object sender, RoutedEventArgs e)
{
string name = NameBox.Text.Trim();
if (name.Length == 0)
{
GreetingText.Text = "Please type your name first.";
return;
}
GreetingText.Text = $"Hello, {name}! Welcome to WPF.";
}
Let us read it slowly:
- The method name
SayHello_Clickmatches theClick="SayHello_Click"in XAML exactly. That is how WPF links the two. senderis the control that raised the event (the button).eholds extra details. You do not need either yet.NameBox.Textreads what the user typed. You can useNameBoxhere because you gave itx:Name="NameBox"in XAML.GreetingText.Text = ...changes the text of the secondTextBlock.
Run the app, type your name and click Say hello. Your first working WPF app is done.
You will learn much more about events in Code-Behind and Event Handlers. If C# events are new to you, the events lesson in the C# course explains the idea behind them.
Step 7: Small improvements
Two little changes make the app feel nicer.
Press Enter to click
Set IsDefault="True" on the button. Now pressing Enter anywhere in the window clicks it:
<Button Content="Say hello" IsDefault="True" ... />
Start with the cursor in the text box
Use FocusManager.FocusedElement on the window so the text box has keyboard focus when the app opens:
<Window ...
FocusManager.FocusedElement="{Binding ElementName=NameBox}">
The curly braces are a markup extension, a special XAML shortcut. You will meet them properly in a later lesson. For now, just know it points at the control named NameBox.
Hot Reload: change things while the app runs
Visual Studio has XAML Hot Reload. Start the app with F5, then change a Text or FontSize in MainWindow.xaml and save. The running window updates right away, without a restart. This makes trying out layouts much faster.
From the command line you can get a similar effect for C# changes with:
dotnet watch
Common mistakes
- The name in
Clickand the method name do not match. The build fails with an error saying the window does not contain a definition for the method. Check the spelling and capital letters. - Forgetting
x:Name. Without it,NameBoxdoes not exist in C#, and you get “the name NameBox does not exist in the current context”. - Putting two children directly inside
Window. AWindowcan hold only one child. That is why we use aStackPanelto hold the others. - Editing while the app is running from the command line. The build may fail because the
.exefile is in use. Close the window first.
Try it yourself
- Change the greeting to also show the time with
DateTime.Now.ToShortTimeString(). - Add a second button called Clear that empties both the text box and the greeting.
- Change the
FontSizeandForegroundof the greeting, for exampleForeground="DarkGreen".
Quick recap
dotnet new wpf -n Greeter(or WPF Application in Visual Studio) creates a working app.MainWindow.xamldescribes the window, andMainWindow.xaml.csholds its C# code.StackPanel,TextBlock,TextBoxandButtonare enough for a simple form.x:Namelets C# reach a control, andClick="MethodName"connects a button to a method.dotnet runor F5 starts the app, and XAML Hot Reload updates it while it runs.- Next, look at every generated file in Understanding the Project Structure.
<!-- MainWindow.xaml -->
<Window x:Class="Greeter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Greeter" Height="260" Width="400"
FocusManager.FocusedElement="{Binding ElementName=NameBox}">
<!-- A Window holds one child, so a StackPanel holds the rest -->
<StackPanel Margin="20">
<TextBlock Text="What is your name?" FontSize="16" />
<!-- x:Name makes this TextBox reachable from C# as NameBox -->
<TextBox x:Name="NameBox" Margin="0,8,0,0" />
<!-- Click names the C# method to run. IsDefault: Enter clicks it -->
<Button Content="Say hello" Margin="0,12,0,0"
HorizontalAlignment="Left" Padding="12,4"
IsDefault="True" Click="SayHello_Click" />
<Button Content="Clear" Margin="0,8,0,0"
HorizontalAlignment="Left" Padding="12,4"
Click="Clear_Click" />
<!-- The greeting appears here -->
<TextBlock x:Name="GreetingText" Margin="0,16,0,0" FontSize="16"
Foreground="DarkGreen" TextWrapping="Wrap" />
</StackPanel>
</Window>
// MainWindow.xaml.cs
using System.Windows;
namespace Greeter;
public partial class MainWindow : Window
{
public MainWindow()
{
// Builds the controls described in MainWindow.xaml
InitializeComponent();
}
// Runs when "Say hello" is clicked (or Enter is pressed)
private void SayHello_Click(object sender, RoutedEventArgs e)
{
string name = NameBox.Text.Trim();
if (name.Length == 0)
{
GreetingText.Text = "Please type your name first.";
return;
}
GreetingText.Text = $"Hello, {name}! Welcome to WPF. It is {DateTime.Now.ToShortTimeString()}.";
}
// Runs when "Clear" is clicked
private void Clear_Click(object sender, RoutedEventArgs e)
{
NameBox.Text = "";
GreetingText.Text = "";
NameBox.Focus(); // put the cursor back in the box
}
}
Was this explanation helpful?
Your feedback helps us improve the content for everyone.
Thank you for your feedback!
We appreciate you helping us improve.
What could we improve? (Optional)
Read aloud
Ready