Getting Started / Doc

Topics:

How to get started?

It’s very easy!
 
  1. Reference the “XAML for Blazor” package (on NuGet.org) from your “Blazor WebAssembly” project (note: “Blazor Server” support is on the roadmap). 
     
  2. Optionally, install this VSIX that will add some “item templates” to Visual Studio 2022. It lets you create new XAML files in Blazor projects via the “Add New Item” dialog.
         
  3. Add XAML files to your Blazor WebAssembly project.

    (Note: If you copy/paste XAML files from your disk, make sure that their “Build Action” is set to “Content” or “Page” instead of “None“)

  4. Instantiate your XAML controls (or instantiate the built-in types like DataGrid, DataForm, etc.) from within Razor pages by using the following Razor code: <XamlForBlazor.XamlElement Type=”typeof(UserControl1)”/>
     
       

  5. You can also pass values and register events like this: <XamlForBlazor.XamlElement Type=”typeof(UserControl1)” MyXamlProperty = “@myBlazorValue” ExampleOfEvent = “@UserControl1_MyEventHandler” />

    (Note: remember to use the “@” sign when passing dynamic values or registering event handlers) 

 

Is there a sample project?

Yes, a simple Blazor WebAssembly application (“Hello World”) with some XAML files can be found at:

Xaml for Blazor example on GitHub.

This source code corresponds to this tutorial.

What are the known limitations?

  • Only “Blazor WebAssembly” is supported at the moment (“Blazor Server” is on the roadmap)
     
  • Requires .NET 7 or .NET 8. Presently tested only on Visual Studio 2022 on Windows
  • You can place XAML files and Razor files side-by-side within the same Blazor project, but you cannot mix and match snippets of XAML and snippets of Razor within a single file yet. 
  • The primary supported dialect of XAML is that of Microsoft Silverlight (documentation), which is a browser-friendly subset of WPF. Porting snippets of XAML from WPF, UWP or WinUI is relatively easy. Porting from Xamarin Forms or .NET MAUI requires more substantial work. In all cases, please contact Userware for migration services.

Troubleshooting - What if it doesn't work?

Please start by double-checking the pre-requisites:

  • Verify that your project is of type “Blazor WebAssembly
  • Verify that your project is using either .NET 7 or .NET 8. Please verify the <TargetFramework> tag in the project file (.CSPROJ): <TargetFramework> net7.0 </TargetFramework>
  • Try updating to the very latest version of Visual Studio 2022 (Note: more IDEs are on the roadmap)
  • Make sure you are running on Windows (Note: more platforms are on the roadmap)
  • Make sure that your project is referencing the  “XAML for Blazor” package from NuGet.org
  • Make sure that you have properly installed the VSIX (only useful for the “Add New Item” dialog of Visual Studio
Then, please check the following: 
  • Look for error messages in the browser Console. To do so, press F12 or Ctrl+Shift+I or open the Developer Tools via the browser menu (while the application is running), then click on “Console”.
  • Make sure that your .XAML files have the property “Build Action” set to “Content” or “Page”. To do so, select the XAML file in the Solution Explorer, press F4 to open its properties, and choose “Content” under “Build Action”.   + Also, make sure that “Custom Tool” is set to “MSBuild:Compile”. It happens frequently that copy/pasting XAML files from File Explorer sets the “Build Action” to “None”. You need to change it to “Content” or “Page”.
  • Try emptying the browser Cache and reloading. To do so, right-click on Reload button while the F12 browser Developer Tools are open, and then click “Empty cache and reload”.
  •  Try cleaning the browser’s WebAssembly “Application Cache Storage” (not the same as the browser Cache). To do so, expand “Cache Storage” under the “Application” tab of the F12 browser Developer Tools (see screenshot below), then right-click on what’s inside and click “Delete”.
 

If you still encounter any issues, please contact us at: xaml-for-blazor@userware.onmicrosoft.com

 

How to create a new XAML file in my Blazor project?

After installing the VSIX and referencing the “XAML for Blazor” package, you will see some item templates in the “Add New Item” dialog. Just right-click on the project name in the Solution Explorer, click “Add”, then click “New item…”:


(If you don’t see these options, please ensure that you have installed this VSIX)

How to register XAML events from Razor?

XAML and Razor share the same DOM, the same memory, and the same thread. This makes it very easy to pass objects from one to the other, and to register events.

The following example shows how to register an event of a UIElement.

In the code below, the “Click” event of the XAML built-in “Button” control is registered in a Razor page (Counter.razor).

The same can be applied to any event from any UIElement, including your own custom UserControls.

@page "/counter"

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<!-- This is how to load a XAML control and register an event.
     You can replace 'Button' with your own UserControl. -->
     
<XamlForBlazor.XamlElement
    Type="typeof(System.Windows.Controls.Button)"
    Content="Click me"
    Click="@Button_Click"
    FontSize="16"/>

<!-- The code below comes from the default stuff that was in the Blazor project: -->
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }

    private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        currentCount++;
        base.StateHasChanged();
        System.Windows.MessageBox.Show("Remember the good old MessageBox?");
    }
}

Here is a screenshot that shows how it renders when the application runs.

(Notice the “Click me” button that has the familiar XAML look – which you can obviously customize via XAML Styles)


Step-by-step tutorial (from A to Z):

1. Let’s start by installing this optional Visual Studio Extention (VSIX) which adds some “item templates” to the “Add New File” dialog of Visual Studio. It will facilitate the creation of new XAML files inside Blazor projects.

2. Now let’s launch Visual Studio 2022 and create a new Blazor WebAssembly application named “BlazorApp1”:

 

Let’s choose “.NET 7” when creating the Blazor project:

 

3. Now we need to add a reference to the “XAML for Blazor” package from NuGet.org.

To do so, let’s right-click on the Blazor project in the Solution Explorer and click “Manage NuGet Packages…“, then search for “xaml for blazor” and click “Install“:

 

 

An alternative way is to simply add the following line to your CSPROJ:

<PackageReference Include="XamlForBlazor" Version="1.2.*" />

4. It’s finally time to play with some XAML!

Let’s start with a simple goal: let’s display the XAML built-in “DataGrid” and “DataForm” controls inside the “FetchData.razor” sample file.

Edit the file “FetchData.razor”:

 

 Let’s add a XAML read-only DataGrid (see DataGrid documentation) and an editable DataForm (see DataFrom documentation) by adding the following code to our “FetchData.razor” file:

    <!-- Let's add a readonly DataGrid and an editable DataForm -->

    <XamlForBlazor.XamlElement Type="typeof(System.Windows.Controls.DataGrid)"
                               ItemsSource="@forecasts"
                               IsReadOnly="True" />

    <XamlForBlazor.XamlElement Type="typeof(System.Windows.Controls.DataForm)"
                               ItemsSource="@forecasts"
                               Width="300" />

When running the application, this is what we get:

Notice how the DataForm control comes with nice features such as built-in validation:

You can learn more about the DataForm control here.

When playing with the app, you may notice that when a value is changed in the DataForm, the Blazor HTML table is not updated.

To fix this, we can register the “EditEnded” event of the DataForm, and call the “base.StateHasChanged()” method of Blazor, as shown below:

The Blazor HTML table will now update automatically when editing the values in the DataForm (please note that you need to move to the next record to commit the values change).

Note: if you want to also have the DataGrid be automatically updated when the values of the DataForm are changed, you can make the “WeatherForecast” class implement the interface named “System.ComponentModel.INotifyPropertyChanged”.

5. To conclude, let’s create a XAML UserControl.

To do so, right-click on the project name in the Solution Explorer, then click “Add”, and then click “New item…”:

Click “Show All Templates”:

Choose “XAML UserControl (XAML for Blazor)”:

(Remember to install the VSIX to see those options)

Let’s call it “UserControl1”.

Let’s also add a new “Class” named “ViewModel1”.

Here is a screenshot of what the project should look like:


 Notice that the newly created XAML UserControl appears side-by-side with the Razor files.

Let’s put the following code into “UserControl1.xaml“:

 

<UserControl
    x:Class="BlazorApp1.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    <StackPanel Orientation="Vertical">
        
        <TextBlock FontSize="18">Current count: <Run Text="{Binding CurrentCount}"/></TextBlock>
        
        <Button Content="Increment Count"
                Click="ButtonIncrementCount_Click"
                Margin="0,20,0,0"
                FontSize="18"
                HorizontalAlignment="Left"/>

    </StackPanel>
    
</UserControl>

Let’s put this other code into “UserControl1.xaml.cs“:

 

using System.Windows;
using System.Windows.Controls;

namespace BlazorApp1
{
    public partial class UserControl1 : UserControl
    {
        readonly ViewModel1 _viewModel = new();

        public UserControl1()
        {
            this.InitializeComponent();

            this.DataContext = _viewModel;
        }

        private void ButtonIncrementCount_Click(object sender, RoutedEventArgs e)
        {
            _viewModel.CurrentCount++;
        }
    }
}

Let’s put this  into “ViewModel1.cs“:

 

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace BlazorApp1
{
    public class ViewModel1 : INotifyPropertyChanged
    {
        public int _currentCount;
        public int CurrentCount
        {
            get => _currentCount;
            set
            {
                if (_currentCount == value) return;
                _currentCount = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler? PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string callerName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(callerName));
        }
    }
}

Finally, let’s test our UserControl1 by adding the following line into “Index.razor“:

<XamlForBlazor.XamlElement Type="@typeof(UserControl1)" />

That’s it! Now let’s run and see the result:


What if I have another question?

For any other questions, please contact us at:

xaml-for-blazor@userware.onmicrosoft.com