migrating-wpf-to-dotnet
SKILL.md
WPF .NET Framework → .NET Migration
1. Migration Checklist
1.1 Pre-Migration
- Verify .NET Framework version (4.6.1+ recommended)
- Check NuGet package .NET compatibility
- Verify third-party library .NET versions
- Check Windows Forms interop usage
- Check WCF client usage
- Check ClickOnce deployment usage
1.2 Migration
- Convert project file to SDK style
- NuGet packages.config → PackageReference
- Clean up AssemblyInfo.cs
- app.config → appsettings.json (optional)
- Build and fix errors
- Run tests
1.3 Post-Migration
- Test self-contained deployment
- Test single-file deployment
- Ready to Run (R2R) optimization
- Performance benchmark
2. Project File Conversion
2.1 Old Format (.NET Framework)
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{GUID}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>MyApp</RootNamespace>
<AssemblyName>MyApp</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<!-- ... hundreds of lines ... -->
</PropertyGroup>
<!-- ... -->
</Project>
2.2 New SDK Format (.NET 10)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.*" />
</ItemGroup>
</Project>
3. Step-by-Step Migration
3.1 Try-Convert Tool (Automated)
# Install
dotnet tool install -g try-convert
# Run
try-convert -p MyApp.csproj
3.2 Manual Conversion
Step 1: Create new project file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<RootNamespace>MyApp</RootNamespace>
<AssemblyName>MyApp</AssemblyName>
</PropertyGroup>
</Project>
Step 2: Migrate NuGet references
<!-- packages.config → PackageReference -->
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
</ItemGroup>
Step 3: Clean up AssemblyInfo.cs
SDK style auto-generates most attributes. Keep only custom attributes:
// Properties/AssemblyInfo.cs (keep only necessary items)
using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
[assembly: Guid("your-guid-here")]
Disable generation in project file (if needed):
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
4. Breaking Changes
4.1 Removed APIs
| API | .NET Framework | .NET Alternative |
|---|---|---|
BinaryFormatter |
✅ | ⚠️ Removed for security. Use System.Text.Json |
AppDomain.CreateDomain |
✅ | ❌ Not supported |
Remoting |
✅ | ❌ Use gRPC, SignalR |
Code Access Security |
✅ | ❌ Removed |
4.2 WCF Client
<!-- WCF client (server not supported) -->
<ItemGroup>
<PackageReference Include="System.ServiceModel.Http" Version="8.0.*" />
<PackageReference Include="System.ServiceModel.Primitives" Version="8.0.*" />
</ItemGroup>
4.3 Windows Forms Interop
<PropertyGroup>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
5. Dual Targeting (Gradual Migration)
5.1 Multi-Target
<PropertyGroup>
<TargetFrameworks>net48;net10.0-windows</TargetFrameworks>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0-windows'">
<PackageReference Include="Microsoft.Windows.Compatibility" Version="9.0.*" />
</ItemGroup>
5.2 Conditional Compilation
#if NET48
// .NET Framework specific code
System.Configuration.ConfigurationManager.AppSettings["Key"];
#else
// .NET specific code
Microsoft.Extensions.Configuration.IConfiguration config;
#endif
6. Modern .NET Features
6.1 Nullable Reference Types
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
public partial class MainViewModel : ObservableObject
{
[ObservableProperty] private string? _optionalValue;
[ObservableProperty] private string _requiredValue = string.Empty;
}
6.2 File-Scoped Namespaces
// Old
namespace MyApp.ViewModels
{
public class MainViewModel { }
}
// New
namespace MyApp.ViewModels;
public class MainViewModel { }
6.3 Global Usings
// GlobalUsings.cs
global using System;
global using System.Collections.Generic;
global using System.Collections.ObjectModel;
global using System.Linq;
global using System.Threading.Tasks;
global using CommunityToolkit.Mvvm.ComponentModel;
global using CommunityToolkit.Mvvm.Input;
7. Deployment
7.1 Self-Contained
dotnet publish -c Release -r win-x64 --self-contained true
7.2 Single File
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>
7.3 Ready to Run (AOT)
<PropertyGroup>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
8. Common Issues
| Issue | Solution |
|---|---|
System.Drawing error |
Add System.Drawing.Common NuGet |
| WCF server code | Migrate to CoreWCF or gRPC |
app.config reading |
Use Microsoft.Extensions.Configuration |
| XAML designer error | Requires Visual Studio 2022 17.8+ |
| ClickOnce | Replace with MSIX or custom updater |
9. Resources
Weekly Installs
4
Repository
christian289/do…audecodeGitHub Stars
16
First Seen
Feb 28, 2026
Security Audits
Installed on
cline4
github-copilot4
codex4
kimi-cli4
gemini-cli4
cursor4