Overview
This guide covers the steps required to update a Microsoft .NET MAUI project that uses the Zebra EMDK for Xamarin SDK from .NET 6 (or later) to .NET 10.
Starting with .NET 8, the MAUI SDK introduced changes that affect all existing MAUI projects:
<UseMaui>true</UseMaui>no longer automatically includes MAUI NuGet packages.
An explicitPackageReferenceforMicrosoft.Maui.Controlsis now required.Application.MainPageis deprecated. Application startup must use theCreateWindow()override instead.Symbol.XamarinEMDKis scoped to the Android target framework via a build condition in the.csproj, and therefore that condition must be updated alongside the framework moniker.
If not addressed, all three issues appear as build warnings (MA002, CS0618) or silently break package restore.
Requirements
- Visual Studio 2022 v17.12 (or later)
- .NET SDK 10.0 (or later)
- .NET MAUI workload - If not already installed, see below.
- Symbol.XamarinEMDK - Available on NuGet; verify the version is compatible with your EMDK on-device service.
- Zebra Android device running Android 5.0 (API 21 or later) with EMDK service installed.
Verify current .NET version using the .NET CLI:
dotnet --version
Install the MAUI workload if missing:
dotnet workload install maui
Summary of Changes
Below is a list of the files that must change for a successful mitgration. Details and steps for making the changes follow.
Files to Update
.csproj<TargetFrameworks>:- Replace
net6.0-*(or earlier) withnet10.0-*to target the .NET 10 runtime.
- Replace
.csprojnew<ItemGroup>:- Add
Microsoft.Maui.Controlspackage reference, which stopped being auto-included in .NET 8+ (errorMA002)
- Add
.csprojSymbol.XamarinEMDKcondition:- Update
net6.0-androidtonet10.0-androidso the condition matches the updated target framework moniker.
- Update
App.xaml.cs:- Replace
MainPage = new AppShell()withCreateWindow()override;MainPagebecame obsolete in .NET 8+ (errorCS0618)
- Replace
.csproj.user(optional):- Update
<ActiveDebugFramework>moniker for IDE debug toolbar alignment.
- Update
YourProject.csproj:- Update target framework monikers; add explicit MAUI package reference; update EMDK package condition.
App.xaml.cs:- Replace deprecated
MainPageassignment withCreateWindow()override.
- Replace deprecated
I. Update Target Frameworks
- Open your
.csprojfile and replace allnet6.0,net7.0,net8.0ornet9.0prefixes withnet10.0across every target framework moniker. - Update any other platform monikers in the same way. Tizen is shown as an example in the commented statements below.
Example
Before:
<TargetFrameworks>net6.0-android;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net6.0-windows10.0.19041.0</TargetFrameworks>
<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->
After:
<TargetFrameworks>net10.0-android;net10.0-ios;net10.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net10.0-windows10.0.19041.0</TargetFrameworks>
<!-- <TargetFrameworks>$(TargetFrameworks);net10.0-tizen</TargetFrameworks> -->
II. Add Explicit Microsoft.Maui.Controls Package Reference
Starting with .NET 8, <UseMaui>true</UseMaui> no longer pulls in MAUI NuGet packages automatically. Without this reference, the build produces warning MA002, potentially causing MAUI types not to resolve.
Add the following <ItemGroup> to your .csproj before the resource definitions:
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
</ItemGroup>
$(MauiVersion) is an MSBuild property automatically set by the MAUI SDK to match your installed workload version. It keeps the reference in sync whenever the workload is updated.
To pin to a specific version instead, replace $(MauiVersion) with the version number reported in the MA002 warning when you first build (for example, 10.0.20).
III. Update Symbol.XamarinEMDK Package Condition
Symbol.XamarinEMDK is scoped to Android using a Condition on its <ItemGroup>. This condition must be updated to match the new target framework moniker, otherwise the package will not be restored for the Android build.
Example
Before:
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0-android'">
<PackageReference Include="Symbol.XamarinEMDK">
<Version>8.0.0.2</Version>
</PackageReference>
</ItemGroup>
After:
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0-android'">
<PackageReference Include="Symbol.XamarinEMDK">
<Version>8.0.0.2</Version>
</PackageReference>
</ItemGroup>
The condition value is case sensitive and must exactly match the moniker used in <TargetFrameworks>. The Symbol.XamarinEMDK version number itself requires no change.
IV. Replace MainPage with CreateWindow in App.xaml.cs
Application.MainPage is marked obsolete in .NET 8+ (via warning CS0618). The correct replacement is to override CreateWindow(), which the MAUI framework calls when it needs to create the application window.
Open App.xaml.cs and modify as shown below:
Example
Before:
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
}
After:
public partial class App : Application
{
public App()
{
InitializeComponent();
}
protected override Window CreateWindow(IActivationState activationState)
{
return new Window(new AppShell());
}
}
This change is needed because in .NET 8+, MAUI introduced multi-window support, but setting MainPage directly bypasses the windowing lifecycle and does not work correctly on all platforms. The CreateWindow() override is the supported entry point for constructing the initial page.
V. Update .csproj.user File (optional)
The .csproj.user file is developer-local option that stores IDE settings such as the last-selected debug target. It is typically excluded from source control, but if present, it might reference the old framework moniker and cause the wrong target to appear pre-selected in Visual Studio.
If you've opted to use this feature, ensure correct operation by locating the <ActiveDebugFramework> element and updating it as shown below:
Example
Before:
<ActiveDebugFramework>net6.0-android</ActiveDebugFramework>
After:
<ActiveDebugFramework>net10.0-android</ActiveDebugFramework>
NOTE: This has no effect on the build output; it affects only the Visual Studio debug toolbar default.
Build Verification
After completing all of the steps above, verify that the project is building properly using one of the methods below.
Verify Using .NET CLI:
dotnet build YourProject.csproj -f net10.0-android
Expected output:
> Build succeeded.
> 0 Warning(s)
> 0 Error(s)
Verify Using Visual Studio:
- Open your
.slnfile in Visual Studio 2022. - Select Build > Rebuild Solution.
- Confirm the Output window shows 0 errors and 0 warnings.
Troubleshooting
MA002 — MAUI NuGet packages not included
Starting with .NET 8, setting <UseMaui>true</UseMaui> does not automatically include NuGet package references in your project.
The fix is to update your project by including: <PackageReference Include="Microsoft.Maui.Controls" ... />. See how to add the explicit Microsoft.Maui.Controls package reference described in Step II.
CS0618 — Application.MainPage is obsolete
- Message: "‘Application.MainPage.set’ is obsolete: This property is deprecated. Initialize your application by overriding Application.CreateWindow rather than setting MainPage."
- Fix: Replace the
MainPageassignment with theCreateWindow()override described in Step IV.
CS8632 — Nullable annotation outside nullable context
Message: "The annotation for nullable reference types should only be used in code within a ‘#nullable’ annotations context."
Cause: Occurs if the
IActivationState?parameter (with the?nullable annotation) is used in a project that does not have<Nullable>enable</Nullable>enabled.Fix: Remove "
?" from the parameter type inCreateWindow():// Correct — no nullable annotation protected override Window CreateWindow(IActivationState activationState)
NOTE: Do not attempt to resolve by adding "<Nullable>enable</Nullable>" to the project. Doing so enables strict nullable analysis across all files and could produce a large number of new warnings in existing the EMDK sample code, which was not written with nullability in mind.
Symbol.XamarinEMDK not restored
If the Symbol.XamarinEMDK package fails to restore after a condition update, verify that the Condition value in the .csproj exactly matches the target framework moniker in <TargetFrameworks> as shown below:
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0-android'">
Note that the condition is case sensitive. A mismatch such as Net10.0-Android or a leftover net6.0-android silently skips package restore for the target.