{"id":3058,"date":"2025-12-23T14:59:00","date_gmt":"2025-12-23T14:59:00","guid":{"rendered":"https:\/\/mindfusion.dev\/blog\/?p=3058"},"modified":"2025-12-24T10:10:42","modified_gmt":"2025-12-24T10:10:42","slug":"crafting-a-custom-wpf-virtual-keyboard-a-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/mindfusion.dev\/blog\/crafting-a-custom-wpf-virtual-keyboard-a-step-by-step-guide\/","title":{"rendered":"Building a Custom-Styled WPF Virtual Keyboard: A How-To Guide"},"content":{"rendered":"\n<p>Creating a custom user interface often requires tailoring components to fit your application&#8217;s specific design language. In this guide, we&#8217;ll walk you through how to build and style a WPF virtual keyboard from the ground up, using the powerful <a href=\"https:\/\/mindfusion.dev\/virtual-keyboard-wpf.html\">MindFusion&#8217;s WPF Virtual Keyboard component<\/a>. The result will be a beautiful, resizable keyboard with custom icons, animations, and a clean, maintainable structure.<\/p>\n\n\n\n<p><a href=\"https:\/\/mindfusion.dev\/samples\/wpf\/keyboard\/medical_virtual_keyboard.webp\"><img decoding=\"async\" src=\"https:\/\/mindfusion.dev\/samples\/wpf\/keyboard\/medical_virtual_keyboard.webp\" alt=\"A custom virtual keyboard embedded in a WPF application\"><\/a><\/p>\n\n\n<h2><!--more-->Step 1: Project Setup &amp; NuGet Packages<\/h2>\n<p>First, create a new WPF Application project in Visual Studio. Once your project is ready, you&#8217;ll need to add the virtual keyboard component. You can do this easily via the NuGet Package Manager.<\/p>\n<p>Search for and install the following package:<br \/><a href=\"_wp_link_placeholder\" data-wplink-edit=\"true\">\u00a0MindFusion.Keyboard.Wpf (version 5.1.0)<\/a><\/p>\n<p>This will add all the necessary assemblies to your project.<\/p>\n<h2><!-- Customizing a single key type --><\/h2>\n<h2>Step 2: Defining the Keyboard Layout<\/h2>\n\n\n<p>The structure of the keyboard\u2014what keys are present and where they are located\u2014is defined in a simple XML file. This approach cleanly separates the keyboard&#8217;s layout from its visual styling.<\/p>\n\n\n\n<p>Create an XML file in your project named <code>device.xml<\/code>. Here&#8217;s a snippet showing how to define a few keys:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\"?&gt;\n&lt;KeyboardLayout xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"&gt;\n  &lt;Keys&gt;\n    &lt;!-- A special key, like Enter or Shift --&gt;\n    &lt;Key xsi:type=\"SpecialKey\"&gt;\n      &lt;Content xsi:type=\"xsd:string\"&gt;Enter&lt;\/Content&gt;\n      &lt;Left&gt;555&lt;\/Left&gt;\n      &lt;Top&gt;102&lt;\/Top&gt;\n      &lt;Width&gt;105&lt;\/Width&gt;\n      &lt;Height&gt;40&lt;\/Height&gt;\n      &lt;VirtualKey&gt;13&lt;\/VirtualKey&gt;\n    &lt;\/Key&gt;\n    \n    &lt;!-- A regular character key --&gt;\n    &lt;Key xsi:type=\"RegularKey\"&gt;\n      &lt;Left&gt;105&lt;\/Left&gt;\n      &lt;Top&gt;101&lt;\/Top&gt;\n      &lt;Width&gt;40&lt;\/Width&gt;\n      &lt;Height&gt;40&lt;\/Height&gt;\n      &lt;VirtualKey&gt;65&lt;\/VirtualKey&gt; &lt;!-- 'A' key --&gt;\n    &lt;\/Key&gt;\n  &lt;\/Keys&gt;\n  &lt;Width&gt;675&lt;\/Width&gt;\n  &lt;Height&gt;250&lt;\/Height&gt;\n&lt;\/KeyboardLayout&gt;\n\n<\/code><\/pre>\n\n\n\n<p>Each key is defined with its position, size, and most importantly, its <code>VirtualKey<\/code> code. This numeric code is what the operating system uses to identify the key, and we&#8217;ll use it later for styling.<\/p>\n\n\n\n<p>You can create the XML template for the keyboard fast and easy using online UI keyboard editor: <a href=\"https:\/\/mindfusion.dev\/virtual-keyboard-creator\/index.html\">the Virtual Keyboard Creator.<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Adding and Initializing the Keyboard<\/h2>\n\n\n\n<p>With the layout defined, let&#8217;s add the keyboard to our main window.<\/p>\n\n\n\n<p>In &#8216;MainWindow.xaml&#8217;:<br>We&#8217;ll create a simple <code>Grid<\/code> layout with two rows: one for the keyboard and one for a <code>TextBox<\/code> to see our output.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;Window x:Class=\"KeyboardTest.MainWindow\"\n        xmlns=\"http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation\"\n        xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\"\n        xmlns:vk=\"http:\/\/mindfusion.eu\/keyboard\/wpf\"\n        mc:Ignorable=\"d\"\n        Title=\"MainWindow\" Height=\"500\" Width=\"1150\">\n    &lt;Window.Resources>\n        &lt;ResourceDictionary>\n            &lt;ResourceDictionary.MergedDictionaries>\n                &lt;ResourceDictionary Source=\"MedicalVKStyle.xaml\"\/>\n            &lt;\/ResourceDictionary.MergedDictionaries>\n        &lt;\/ResourceDictionary>\n    &lt;\/Window.Resources>\n\n    &lt;Grid>\n        &lt;Grid.RowDefinitions>\n            &lt;RowDefinition Height=\"*\"\/>\n            &lt;RowDefinition Height=\"Auto\"\/>\n        &lt;\/Grid.RowDefinitions>\n\n        &lt;Border Grid.Row=\"0\" Background=\"#D0E9F2\" BorderThickness=\"5\" BorderBrush=\"#20788C\">\n            &lt;vk:VirtualKeyboard x:Name=\"vk\" Margin=\"0 0 0 0\" \/>\n        &lt;\/Border>\n\n        &lt;TextBox Grid.Row=\"1\" x:Name=\"outputTextBox\" Margin=\"10\" MinHeight=\"50\" AcceptsReturn=\"True\" VerticalScrollBarVisibility=\"Auto\"\/>\n    &lt;\/Grid>\n&lt;\/Window><\/code><\/pre>\n\n\n\n<p>Notice we&#8217;ve also added a &#8220;ResourceDictionary&#8221; that points to &#8220;MedicalVKStyle.xaml&#8221;\u2014this is where we&#8217;ll put all our styling.<\/p>\n\n\n\n<p>In &#8220;MainWindow.xaml.cs&#8221;:<br>In the code-behind, we initialize the keyboard, load our &#8220;device.xml&#8221; layout, and link the keyboard&#8217;s output to our &#8220;TextBox&#8221;.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public partial class MainWindow : Window\n{\n    public MainWindow()\n    {\n        InitializeComponent();\n        \n        vk.IsStandAlone = false;\n        vk.TemplateLayout = KeyboardLayout.Create(\"device.xml\");\n        vk.Background = Brushes.SkyBlue;\n        vk.LayoutRing.Add(KeyboardLayout.Create(\"device.xml\"));\n        vk.ApplyTemplate();\n        \n        \/\/ Link the keyboard to the TextBox\n        vk.InputTarget = outputTextBox;\n    }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Creating a Custom Style in XAML<\/h2>\n\n\n\n<p>This is where the styling happens. We create a new &#8220;ResourceDictionary&#8221; file named &#8220;MedicalVKStyle.xaml&#8221; to define the keyboard&#8217;s look and feel. This approach keeps our styles neatly organized and separate from the main window&#8217;s layout.<\/p>\n\n\n\n<p><strong>The Base Style for All Keys<\/strong><br>To avoid repeating code, we define a single base style that all keys will use. This <code>BaseKeyStyle<\/code> defines the background gradient, border, drop shadow, and interactive animations (like changing color on mouse-over or click).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- Base Style for all keys --&gt;\n&lt;Style x:Key=\"BaseKeyStyle\" TargetType=\"{x:Type ContentControl}\"&gt;\n    &lt;Setter Property=\"Template\"&gt;\n        &lt;Setter.Value&gt;\n            &lt;ControlTemplate TargetType=\"{x:Type ContentControl}\"&gt;\n                &lt;!-- ... Storyboards for animations ... --&gt;\n                &lt;Grid&gt;\n                    &lt;Rectangle x:Name=\"rectangle\" RadiusY=\"3\" RadiusX=\"3\"&gt;\n                        &lt;Rectangle.Effect&gt;\n                            &lt;DropShadowEffect ShadowDepth=\"1\" BlurRadius=\"2\" Direction=\"267\"\/&gt;\n                        &lt;\/Rectangle.Effect&gt;\n                        &lt;Rectangle.Fill&gt;\n                            &lt;LinearGradientBrush EndPoint=\"0.5,1\" StartPoint=\"0.5,0\"&gt;\n                                &lt;GradientStop Color=\"#FF20788C\" Offset=\"0\"\/&gt;\n                                &lt;GradientStop Color=\"#FF2aa1bb\" Offset=\"1\"\/&gt;\n                            &lt;\/LinearGradientBrush&gt;\n                        &lt;\/Rectangle.Fill&gt;\n                    &lt;\/Rectangle&gt;\n                    &lt;ContentPresenter HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"\/&gt;\n                &lt;\/Grid&gt;\n                &lt;!-- ... ControlTemplate.Triggers for events ... --&gt;\n            &lt;\/ControlTemplate&gt;\n        &lt;\/Setter.Value&gt;\n    &lt;\/Setter&gt;\n&lt;\/Style&gt;\n\n&lt;!-- Implicitly apply this style to all ContentControls --&gt;\n&lt;Style TargetType=\"{x:Type ContentControl}\" BasedOn=\"{StaticResource BaseKeyStyle}\"\/&gt;<\/code><\/pre>\n\n\n\n<p><strong>Styling Special Keys with DataTriggers<\/strong><br>For special keys like &#8216;Shift&#8217;, &#8216;Enter&#8217;, and &#8216;Backspace&#8217;, we want to display custom icons instead of text. We achieve this declaratively in XAML using &#8220;DataTrigger&#8221;s.<\/p>\n\n\n\n<p>First, we define simple &#8220;DataTemplate&#8221;s that contain only the icon &#8220;Path&#8221; data.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- DataTemplate for the Backspace icon --&gt;\n&lt;DataTemplate x:Key=\"key_BACKSPACE\"&gt;\n    &lt;Grid&gt;\n        &lt;Path Fill=\"#FFD0E9F2\" Stretch=\"None\" Stroke=\"#FF20788C\" \n              Data=\"M21,11H6.83l3.58-3.59L9,6l-6,6,6,6,1.41-1.41L6.83,13H21V11Z\" \n              HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"\/&gt;\n    &lt;\/Grid&gt;\n&lt;\/DataTemplate&gt;<\/code><\/pre>\n\n\n\n<p>Then, in the &#8220;DataTemplate&#8221; for &#8220;vk:SpecialKey&#8221;, we create a &#8220;Style&#8221; that switches the &#8220;ContentTemplate&#8221; based on the key&#8217;s &#8220;VirtualKey&#8221; code.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;DataTemplate DataType=\"{x:Type vk:SpecialKey}\">\n    &lt;ContentControl Content=\"{Binding .}\" VerticalContentAlignment=\"Center\" HorizontalContentAlignment=\"Center\">\n        &lt;ContentControl.Style>\n            &lt;Style TargetType=\"ContentControl\" BasedOn=\"{StaticResource BaseKeyStyle}\">\n                &lt;Setter Property=\"ContentTemplate\" Value=\"{StaticResource key_Def}\"\/>\n                &lt;Style.Triggers>\n                    &lt;!-- When VirtualKey is 16 (Shift), use the Shift icon template -->\n                    &lt;DataTrigger Binding=\"{Binding VirtualKey}\" Value=\"16\">\n                        &lt;Setter Property=\"ContentTemplate\" Value=\"{StaticResource key_SHIFT}\"\/>\n                    &lt;\/DataTrigger>\n                    &lt;!-- When VirtualKey is 8 (Backspace), use the Backspace icon template -->\n                    &lt;DataTrigger Binding=\"{Binding VirtualKey}\" Value=\"8\">\n                        &lt;Setter Property=\"ContentTemplate\" Value=\"{StaticResource key_BACKSPACE}\"\/>\n                    &lt;\/DataTrigger>\n                    &lt;!-- ... Other triggers for Enter, Tab, etc. ... -->\n                &lt;\/Style.Triggers>\n            &lt;\/Style>\n        &lt;\/ContentControl.Style>\n    &lt;\/ContentControl>\n&lt;\/DataTemplate>\n\n\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">In Addition: Applying the Predefined Virtual Keyboard Styles<\/h2>\n\n\n\n<p>The Virtual Keyboard component itself comes with 10+ predefined styles. There&#8217;s plenty to choose from, so you might want to utilize what is already available. Here&#8217;s how it&#8217;s done:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Comment the code that loads the custom template file (MedicalVKStyle.xaml) in MainWindow.xaml:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>...................   \n xmlns:local=\"clr-namespace:KeyboardTest\"\n    mc:Ignorable=\"d\"\n    Title=\"MainWindow\" Height=\"500\" Width=\"1150\">\n&lt;!--&lt;Window.Resources>\n    &lt;ResourceDictionary>\n        &lt;ResourceDictionary.MergedDictionaries>\n            &lt;ResourceDictionary Source=\"MedicalVKStyle.xaml\">&lt;\/ResourceDictionary>\n        &lt;\/ResourceDictionary.MergedDictionaries>\n    &lt;\/ResourceDictionary>\n&lt;\/Window.Resources>-->\n\n&lt;Grid>\n    &lt;Grid.RowDefinitions>\n................<\/code><\/pre>\n\n\n\n<p>2. Import the namespace &#8220;MindFusion.UI.Wpf;&#8221;, which is part of the Virtual Keyboard NuGet package. In the constructor, specify the desired colour scheme this way:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using MindFusion.UI.Wpf;\n...........\n\n {\n     InitializeComponent();\n\t\n     ColorScheme.Scheme = Scheme.OfficeGreen;\n}<\/code><\/pre>\n\n\n\n<p>Note that you do not need to apply the theme on the VirtualKeyboard instance directly. <\/p>\n\n\n\n<p>Now, when you run the sample, instead of the custom-styled medical keyboard, the Office-Green styled keyboard is loaded:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2025\/12\/virtual_keyboard_green_style.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"512\" src=\"https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2025\/12\/virtual_keyboard_green_style-1024x512.png\" alt=\"MindFusion WPF Virtual Keyboard component in the 'Office Green' theme\" class=\"wp-image-3082\" srcset=\"https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2025\/12\/virtual_keyboard_green_style-1024x512.png 1024w, https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2025\/12\/virtual_keyboard_green_style-300x150.png 300w, https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2025\/12\/virtual_keyboard_green_style-768x384.png 768w, https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2025\/12\/virtual_keyboard_green_style-500x250.png 500w, https:\/\/mindfusion.dev\/blog\/wp-content\/uploads\/2025\/12\/virtual_keyboard_green_style.png 1029w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p class=\"has-text-align-center\"><strong><a href=\"https:\/\/mindfusion.dev\/samples\/wpf\/keyboard\/MedicalVirtualKeyboard.zip\">Download the sample: complete source code and links to the NuGet package<\/a><\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>And there you have it! By combining an XML layout file with a powerful and reusable XAML styling system, we&#8217;ve created a fully custom and visually appealing <a href=\"https:\/\/mindfusion.dev\/virtual-keyboard-wpf.html\">WPF virtual keyboard<\/a>. This approach keeps the design clean, maintainable, and easy to update, separating the keyboard&#8217;s structure from its appearance and behavior.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-dots\"\/>\n\n\n\n<p><em>About MindFusion Virtual Keyboard for WPF: <\/em>The<a href=\"https:\/\/mindfusion.dev\/virtual-keyboard-wpf.html\"> MindFusion Virtual Keyboard for WPF<\/a> is a powerful and highly customizable on-screen input solution, perfect for touch-enabled applications in specialized environments. As demonstrated in this guide for creating a custom medical keyboard, its flexible design empowers developers to create bespoke layouts tailored to unique industry demands,ensuring secure and intuitive data entry. Integrate it seamlessly into your WPF applications to provide a robust and adaptable user experience.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating a custom user interface often requires tailoring components to fit your application&#8217;s specific design language. In this guide, we&#8217;ll walk you through how to build and style a WPF virtual keyboard from the ground up, using the powerful MindFusion&#8217;s &hellip; <a href=\"https:\/\/mindfusion.dev\/blog\/crafting-a-custom-wpf-virtual-keyboard-a-step-by-step-guide\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[74,343,732],"tags":[730,702,654,391,58],"class_list":["post-3058","post","type-post","status-publish","format-standard","hentry","category-sample-code","category-ui","category-wpf","tag-dev-tools","tag-programming","tag-tutorial","tag-virtual-keyboard","tag-wpf"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3RlKs-Nk","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/3058","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/comments?post=3058"}],"version-history":[{"count":22,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/3058\/revisions"}],"predecessor-version":[{"id":3083,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/3058\/revisions\/3083"}],"wp:attachment":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/media?parent=3058"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/categories?post=3058"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/tags?post=3058"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}