.Net MAUIでXAMLとBlazorをViewModelで連携する方法を紹介していきます。
連携が行えるようになると、XAML側のEntryのテキスト変更をBlazorへ反映できます。
紹介環境
当記事は以下の環境で作成しています。
開発環境
- Visual Studio 2022
- .Net 9
対応方法
ファイル構造は以下で作成しています。良ければ参考にしてください。

手順1:ViewModelを準備します
今回利用するViewModelは、以下のようになります。
using System.ComponentModel;
using System.Runtime.CompilerServices;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.ViewModels;
public class MainViewModel : INotifyPropertyChanged
{
private string _text = "";
public string Text
{
get => _text;
set => OnPropertyChanged(ref _text, value);
}
public event PropertyChangedEventHandler? PropertyChanged;
public void OnPropertyChanged<T>(ref T refValue, T value, [CallerMemberName] string name = "")
{
refValue = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
手順2:XAML側の画面を準備します
先ほど準備したViewModelをXAML側の画面に利用します。ViewModelはRootComponentを利用してBlazor側に渡します。
今回は以下のようになります。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SampleApp"
xmlns:components="clr-namespace:SampleApp.Components"
x:Class="SampleApp.MainPage">
<Grid RowDefinitions="auto,*">
<Entry Grid.Row="0" Text="{Binding Text}" />
<BlazorWebView Grid.Row="1" HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent
x:Name="rootComponent"
Selector="#app"
ComponentType="{x:Type components:Routes}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</Grid>
</ContentPage>
using SampleApp.Components;
using SampleApp.ViewModels;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp;
public partial class MainPage : ContentPage
{
private MainViewModel _viewModel = new();
public MainPage()
{
InitializeComponent();
this.BindingContext = _viewModel;
rootComponent.Parameters =
new Dictionary<string, object?>
{
{ nameof(Routes.ViewModel), _viewModel }
};
}
}
手順3:Blazor側の画面を準備します
Blazor側の画面では、ルーターとページを用意していきます。
ルーターでViewModelを受け止めるには、Parameter属性を利用します。
今回は以下のようになります。
@using SampleApp.ViewModels
<Router AppAssembly="@typeof(MauiProgram).Assembly">
<Found Context="routeData">
<CascadingValue Value="ViewModel">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
</CascadingValue>
</Found>
</Router>
@code {
[Parameter]
public MainViewModel? ViewModel { get; set; }
}
ページでViewModelを受け止めるには、CascadingParameter属性を利用します。XAML側のViewModelの変更を受け付けるためにStateHasChanged()を利用します。
今回は以下のようになります。
@page "/"
@using SampleApp.ViewModels
@using System.ComponentModel
<div>
@ViewModel?.Text
</div>
@code {
[CascadingParameter]
protected MainViewModel? ViewModel { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
if (ViewModel is not null)
{
ViewModel.PropertyChanged += OnPropertyChanged;
}
}
private void OnPropertyChanged(object? sender, PropertyChangedEventArgs args)
{
StateHasChanged();
}
}
動作イメージ
以下のようにXAMLとBlazorが連携できるようになります。

終わりに
XAMLとBlazorの連携が上手くいかず、いろいろ試して今回の方法にたどり着くことができました。StateHasChanged()を利用すればいいことに、なかなか気づけず時間がかかりました。この記事や役に立つと幸いです。