Introduction
This is a simple tutorial on how to embed C# code into an XAML file.
Windows-based WPF applications need to respond to user interface events in very specialized ways. Here is where XAML must be supplemented by real programming code. You can put the code in a CS's separate file or embed it directly in the XAML. In this article, I'll be showing the latter approach for the sake of simplicity. For you, it is entirely possible to embed C# code into an XAML file. It's not pretty, but it works. XAML actually supports “code inside” in addition to code behind (somewhat like in ASP.NET). This way can help if you do not wish to use CS's files (I don't know why).
This can be done with the Code
keyword in the XAML language namespace, as explained below.
Using the Code
The first step is to create the WPF Application project in Visual C# and delete C# source code, i.e., files matching a specified CS extension.
The starting point is an XAML template, which is named App.xaml by default. You don't need to change the data of this file.
<Application x:Class="WpfApplicationWithoutCShFiles.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
</Application.Resources>
</Application>
NOTE: The Class
attribute is used in XAML to create a class derived from the element. Visual Studio derives a custom class from Application
class, with the name WpfApplicationWithoutCShFiles
(WpfApplicationWithoutCShFiles
is the name of the project, which is the same as the namespace where the class is defined, and App
is the name that Visual Studio uses for the custom class that is derived from Application
. The App.xaml file must have a Build Action of ApplicationDefinition
, or nothing will work. If you want, you can change the class name to something more exciting.)
The Application
tag not only creates a custom application class, but it also sets the StartupUri
property to identify the XAML document that represents the main window. Notice that the StartupUri
is the Window1.xaml file, which is this one:
<Window x:Class="WpfApplicationWithoutCShFiles.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF Application Without CSharp Files"
SizeToContent="WidthAndHeight"
ResizeMode="CanMinimize"
Height="300" Width="1000">
<Grid Height="255" Width="930">
<Button Margin="400,67,404,126"
Click="ButtonOnClick">
Press the Button
</Button>
<x:Code>
<![CDATA[
</x:Code>
</Grid>
</Window>
Embedded code requires using the x:Code
element and a CDATA
section within the x:Code
element. The XML specification defines CDATA
(which stands for "character data") as a section in an XML file for "blocks of text containing characters which would otherwise be recognized as markup," which is certainly the case for symbols used in C# and other programming languages.
The CDATA
section always begins with the string
"<![CDATA[
" and always ends with the string "]]>"
. The <![CDATA[ ]]>
tag is there to tell XML parsers to ignore anything that is contained within it. Without it, certain C# code might trip up the XML parsing.You must avoid using ]]>
anywhere in the code, because that terminates the CDATA
section!
For example, the following example may lead to the above problem:
m_Data = (arr_one[arr_two[3]]> 100) ? arr_one[arr_two[3]] : 0 ;
You can fix the problem by inserting a little white space somewhere within that inadvertent CDATA
delimiter and all will be well.
This embedded code cannot define fields. The C#'s code can demand fully qualified namespace names if the generated code file does not automatically include using directives for those namespaces. Consider that the embedded code in file Window1.xaml should fully qualify classes in System.Reflection
namespace.
When such an XAML file is compiled, the contents inside the x:Code
element get plopped inside the partial class in the Window1.g.cs file (a C# source file with suffix .g.cs, where the g stands for generated.The code does get generated in the XAML compilation process , but it’s just some “glue code” similar to what had to be written to load and parse a loose XAML file at run-time).
using System;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplicationWithoutCShFiles {
public partial class Window1 : System.Windows.Window,
System.Windows.Markup.IComponentConnector {
private bool _contentLoaded;
#line 17 "..\..\Window1.xaml"
void ButtonOnClick(object sender, RoutedEventArgs args)
{
Button btn = sender as Button;
MessageBox.Show("The button labeled '" +
btn.Content +
"' has been clicked.","Information Message");
}
#line default
#line hidden
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/WpfApplicationWithoutCShFiles;
component/window1.xaml", System.UriKind.Relative);
#line 1 "..\..\Window1.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.ComponentModel.EditorBrowsableAttribute
(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute
("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
void System.Windows.Markup.IComponentConnector.Connect
(int connectionId, object target) {
switch (connectionId)
{
case 1:
#line 12 "..\..\Window1.xaml"
((System.Windows.Controls.Button)(target)).Click +=
new System.Windows.RoutedEventHandler(this.ButtonOnClick);
#line default
#line hidden
return;
}
this._contentLoaded = true;
}
}
}
Although embedding C# code in an XAML file is sometimes convenient, nevertheless, the given technique should not be used too often, because it is not as elegant as a general-purpose solution. Besides making the division between UI and logic messier, loose XAML pages don't support it and Visual Studio doesn't show syntax coloring.
History