Getting Started with Windows Presentation Foundation (WPF) in .NET Core
Time to read: 7 minutes
Windows Presentation Foundation (WPF) is a user interface framework for building desktop applications. Implementing Extensible Application Markup Language (XAML) to define and script views, it has become the standard for Windows application user interfaces. Introduced in 2006, Microsoft has reenergized its commitment to WPF with its inclusion into .NET Core.
The tutorial in this post will guide you through creating a project that will mimic many of the basic functions of a word processor. You will be surprised at how easy it is to implement many features with standard tool elements. You will be introduced to some of the many constructs of WPF and create a foundation for experimenting further.
Prerequisites
You’ll need the following tools and resources to build and run this project:
Windows 10 – It puts the Windows in Windows Presentation Foundation.
.NET Core SDK 3.1 – The SDK includes the APIs, runtime, and CLI.
Visual Studio 2019 with the following workloads and individual components:
- .NET desktop development workload (Includes C#)
- GitHub Extension for Visual Studio (If you want to clone the companion repository.)
You should have a general knowledge of Visual Studio and the C# language syntax. You will be adding and editing files, and debugging code.
There is a companion repository for this post available on GitHub. It contains the complete source code for the tutorial project.
Creating the project
Begin this tutorial by creating a WPF App (.NET Core) project for C# named WPFTwilioExample. You can put the solution and project folders wherever it’s most convenient for you.
While you could easily use this code in a .NET Framework project, this example uses .NET Core, which is closer to the forthcoming .NET 5 release scheduled for November 2020.
After the tooling finishes creating the project, note the presence of the App.xaml file and its associated App.xaml.cs code-behind file. Also examine the MainWindow.xaml and associated code-behind file, MainWindow.xaml.cs.
MainWindow will be the main window for this application and where you will add UI elements. The App class is the entry point to the application and where the MainWindow.xaml is specified as the startup window. You can see this App.xaml file with the line:
If you ever wanted your application to start with another window, this is where you would specify that. For now, leave it as it is.
In the MainWindow.xaml file, note how the main element is a Grid. The Grid is one of several very powerful container components in WPF. Others include StackPanel, Canvas, WrapPanel, UniformGrid and DockPanel. Each has its advantages and situations that it fits best. In this example you will be using the DockPanel.
Replace the existing contents of the MainWindow.xaml file with the following XAML markup:
The changed value for the Title
attribute will be displayed in the window’s title bar when the application runs. Also, note that the DockPanel
element has an attribute of LastChildFill="True"
. While this is the default value, it is done for clarity.
The DockPanel is a container that allows you to dock child controls to the top, bottom, left or right. By default, the last control, if not given a specific dock position, will fill the remaining space. Use the DockPanel whenever you need to dock one or several controls to one of the sides, like for dividing up the window into specific areas. In this example, you will be adding a menu, toolbar, and status elements.
With the window ready you will add components to it which will add capability. The first component you will add is applicable to the window as a whole and will be placed outside of the DockPanel. This will be the CommandBindings section where CommandBinding elements will be defined.
Insert the following XAML markup in the MainWindow.xaml file above the DockPanel
element:
Open the MainWindow.xaml.cs code-behind file and insert the following C# code after the MainWindow()
constructor:
The code block above adds a group of Commands. Commands are constructs that associate a name with an action. They lend to a more loose coupling between UI elements and the code. In this case, you are adding the New, Open, and Save commands. The Executed
attributes in the <CommandBinding>
elements in the MainWindow.xaml file direct the Command to execute the listed method while the CanExecute
attribute points to the CommonCommandBinding_CanExecute
method. The CanExecute
associated method in the code-behind file is run when the app is idle to indicate whether the command can be run or it is disabled. In this case it always returns true. This is useful in situations where a command might be disabled unless certain conditions are met.
The _Execute
handler methods for the New
, Open
and Save
commands in the code behind are provided as stubs for now and will be fleshed out shortly.
You will now be adding the first UI element to the window. Just inside the DockPanel container add a menu with File and Edit top level items by inserting the following XAML markup inside the <DockPanel>
element:
Note how the _File
MenuItem elements reference the Commands that were added earlier.
The _Edit
menu items reference Cut, Copy and Paste, but those CommandBindings were not created. The commands reference the ApplicationCommands.Cut, ApplicationCommands.Copy and ApplicationCommands.Paste commands. These are RoutedCommands and will be processed by the TextBox that you will add shortly. Rather than implement these commands in the code, they’ll use the default behavior of the TextBox element. The application will simply route the commands until an element that can handle them processes them. WPF event routing is a very powerful capability. Routed Events tunnel down the element tree and bubble up the element tree.
But while the menu is now visible, the application still does nothing.
Before going on, look at the design panel and notice how the menu bar that was just added with the <Menu>
element is positioned at the top of the DockPanel. That results from the DocPanel.Doc="Top"
attribute for the Menu
element.
Continuing with the UI elements, add the following code to the MainWindow.xaml file inside the DockPanel
element and after the menu elements you previously inserted:
Here you added a ToolBarTray with several buttons docked to the top, a StatusBar with a TextBlock docked to the bottom, and a RichTextBox as the last element in the DockPanel. Since the RichTextBox is the last element in the DockPanel, it will fill the center of the window.
That takes care of the code in the .xaml file.
You will next add the functionality in the code-behind file MainWindow.xaml.cs which will make the application come alive.
File system dialog boxes use resources from the Microsoft.Win32 and System.IO namespaces, so you will need to add the following using
directives to the others in MainWindow.xaml.cs:
Earlier, you added placeholder stub methods for the New, Open and Save commands. Replace the stub methods with the following code:
New_Executed()
is the handler method for the New command. When a new file is to be created the currently displayed text area will be cleared.
The Open_Executed()
and Save_Executed()
methods are a bit more involved but similar to each other. A dialog box is opened to specify a file to load or save. The file extension applied to the files will be “.rtf” for Rich Text Format.
There are three more things that need to be added to wrap up the functionality:
- Populating the combo boxes
- Taking action when the combo boxes selection changes
- Providing visual feedback for selected text
The combo boxes for the font and the font size in the toolbar need to be populated. That will be done in the MainWindow
class constructor with the following code.
Although the combo boxes have data to display, they still do not do anything. Add the following code after the MainWindow
constructor:
These methods will be invoked when the combo box selections change. They’ll apply the font type and size styling to text that’s selected.
With that completed there is one block of code left to add, the TextBox.SelectionChanged event handler. This method gets called any time there is a change to the selection in the textbox. It is here that all the elements you added (combo boxes, toolbar buttons, statusbar, and the textbox) are synchronized.
Add the following code to the MainWindow.xaml.cs file at the bottom of the MainWindow
class:
This is an interesting block of code. The first thing done is to get the FontFamilyProperty
value from the selected code in the textbox. That value is used to select the related item in the cmbFontFamily
combo box. In this way, the font of the selected code will be selected in the combo box.
The next several lines do the same thing for the font size, font weight, and bold and italic buttons.
Lastly, the status bar is given something to display and shows the selected text.
Note the type checking done in the if
statement prior to setting the cmbFontSize
text. If multiple font sizes are detected in the selected text, the value of temp
will be a data type that’s incompatible with the data type of cmbFontSize.Text
. Checking for the correct data type prevents an error when assigning the property value.
Testing the completed application
Build and run the application. Enter some text in the textbox that fills the center of the app. Select a portion and make it bold or italic. Change the font size and style. When ready, save the file and give it a name. Creating a new file will clear the textbox for something new. Load the file you just saved and you will be able to continue working on it. Note how the selected text attributes are reflected in the toolbar elements. Observe the status bar when text is selected. You should see the selected text.
Potential enhancements
The RichTextBox control has a lot of very powerful editing capabilities. Exposing those capabilities through commands and a handful of UI elements creates a simple, yet powerful text editor.
The layout created here is a standard style window with menu, toolbar, and status bar and is a good foundation for building additional functionality. Consider adding alignment tools to align text to the left or right or centered. Perhaps you wish to add color to your text in terms of a foreground or background color. The status bar could also be expanded to show more pertinent information, such as the number of words in the text box, or even a clock.
Summary
Windows Presentation Foundation is a very powerful tool. It supports layered text, animations, a powerful event and command routing system, and even includes support for elaborate graphics and styling. Microsoft has committed to the future of WPF with its inclusion in .NET Core and .NET 5 due for release later this year. Give it a try. You may be pleasantly surprised.
Additional resources
The following reference resources provide in-depth information on the topics discussed in this post:
Differences in WPF - Differences between Windows Presentation Foundation (WPF) on .NET Core and .NET Framework. WPF for .NET Core.
RichTextBox Overview - Differences between Textbox and RichTextBox
If you’d like to learn how to build a WPF application to verify phone numbers and obtain information about callers and their phones, check out this post:
Using Twilio Lookup in .NET Core WPF Applications
TwilioQuest – If you’d like to learn more about programming C# and other languages, try this action-adventure game inspired by the 16-bit golden era of computer gaming.
Jeffrey Rosenthal is a C/C++/C# developer and enjoys the architectural aspects of coding and software development. Jeff is a MCSD and has operated his own company, The Coding Pit since 2008. When not coding, Jeff enjoys his home projects, rescuing dogs, and flying his drone. Jeff is available for consulting on various technologies and can be reached via email, Twitter, or LinkedIn.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.