From wpf-dev-pack
Migrates WPF apps from .NET Framework to .NET 6+, converting project files to SDK style, updating NuGet packages, and fixing compatibility issues for legacy upgrades.
How this skill is triggered — by the user, by Claude, or both
Slash command
/wpf-dev-pack:migrating-wpf-to-dotnetopusThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- [ ] Verify .NET Framework version (4.6.1+ recommended)
<?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>
<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>
# Install
dotnet tool install -g try-convert
# Run
try-convert -p MyApp.csproj
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>
| 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 |
<!-- WCF client (server not supported) -->
<ItemGroup>
<PackageReference Include="System.ServiceModel.Http" Version="8.0.*" />
<PackageReference Include="System.ServiceModel.Primitives" Version="8.0.*" />
</ItemGroup>
<PropertyGroup>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<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>
#if NET48
// .NET Framework specific code
System.Configuration.ConfigurationManager.AppSettings["Key"];
#else
// .NET specific code
Microsoft.Extensions.Configuration.IConfiguration config;
#endif
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
public partial class MainViewModel : ObservableObject
{
[ObservableProperty] private string? _optionalValue;
[ObservableProperty] private string _requiredValue = string.Empty;
}
// Old
namespace MyApp.ViewModels
{
public class MainViewModel { }
}
// New
namespace MyApp.ViewModels;
public class MainViewModel { }
// 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;
dotnet publish -c Release -r win-x64 --self-contained true
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>
<PropertyGroup>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
| 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 |
npx claudepluginhub christian289/dotnet-with-claudecode --plugin wpf-dev-packMigrating desktop apps. WPF/WinForms to .NET 8+, WPF to WinUI or Uno, UWP to WinUI, decision matrix.
Migrate WPF apps to WinUI 3: namespace replacement, control mapping, threading, imaging, MVVM conversion. Use for converting WPF code or fixing migration build errors.
Guides migration of Xamarin.Android native apps to .NET for Android, covering SDK-style projects, MSBuild properties, AndroidManifest.xml updates, NuGet dependencies, binding libraries, and gotchas.