从桌面应用程序移动到 UWP

如果你有使用 .NET Framework(包括 WPF 和 Windows 窗体)或 C++ Win32 API 构建的现有桌面应用程序,则可以使用多个选项迁移到通用 Windows 平台(UWP)和 Windows 10/11。

在 MSIX 包中打包桌面应用程序

可以在 MSIX 包中打包桌面应用程序,以便访问更多 Windows 10 和 Windows 11 功能。 MSIX 是一种新式 Windows 应用包格式,可为所有 Windows 应用(包括 UWP、WPF、Windows 窗体和 Win32 应用)提供通用打包体验。 在 MSIX 包中打包桌面 Windows 应用可以访问可靠的安装和更新体验、具有灵活功能系统的托管安全模型、对 Microsoft 应用商店、企业管理和许多自定义分发模型的支持。 无论是否具有源代码或只有现有安装程序文件(例如 MSI 或 App-V 安装程序),都可以打包应用程序。 打包应用程序后,可以集成 UWP 功能,例如包扩展和其他 UWP 组件。

有关详细信息,请参阅 从代码生成 MSIX 包需要包标识的功能

使用 Windows 运行时 API

可以直接在 WPF、Windows 窗体或 C++ Win32 桌面应用中调用许多 Windows 运行时 API,从而为 Windows 10 用户带来焕然一新的现代体验。 例如,可以调用 Windows 运行时 API,将 Toast 通知添加到桌面应用。

有关详细信息,请参阅 在桌面应用中使用 Windows 运行时 API

将 .NET Framework 应用迁移到 UWP 应用

如果应用程序在 .NET Framework 上运行,则可以利用 .NET Standard 2.0 将其迁移到 UWP 应用。 将尽可能多的代码移动到 .NET Standard 2.0 类库,然后创建引用 .NET Standard 2.0 库的 UWP 应用。

在 .NET Standard 2.0 库中共享代码

如果应用程序在 .NET Framework 上运行,请将尽可能多的代码放入 .NET Standard 2.0 类库。 只要代码使用标准中定义的 API,就可以在 UWP 应用中重复使用它。 在一个 .NET Standard 库中共享代码比以往更容易,因为 .NET Standard 2.0 中包含了更多 API。

下面是一个视频,告诉你有关它的更多信息。

添加 .NET Standard 库

首先,将一个或多个 .NET Standard 类库添加到解决方案。

添加 .NET Standard 项目

添加到解决方案的库数取决于计划如何组织代码。

确保每个类库文件都以 .NET Standard 2.0为目标。

目标 .NET Standard 2.0

可以在类库项目的属性页中找到此设置。

在桌面应用程序项目中,添加对类库项目的引用。

调用 dot NET 项目的类库引用的解决方案资源管理器窗格的屏幕截图。

接下来,使用工具确定代码符合标准的数量。 这样,在将代码移动到库中之前,可以决定可以重复使用哪些部分、哪些部件需要最少的修改,哪些部分将保持应用程序特定的部分。

检查库和代码兼容性

我们将从从第三方获取的 Nuget 包和其他 dll 文件开始。

如果应用程序使用其中任何一个,请确定它们是否与 .NET Standard 2.0 兼容。 可以使用 Visual Studio 扩展或命令行实用工具执行此操作。

使用这些相同的工具分析代码。 在此处下载工具(dotnet-apiport),然后观看此视频,了解如何使用这些工具。  

如果代码与标准不兼容,请考虑实现该代码的其他方法。 首先打开 .NET API 浏览器。 可以使用该浏览器查看 .NET Standard 2.0 中提供的 API。 请确保将列表的范围限定为 .NET Standard 2.0。

.NET 选项

某些代码特定于平台,需要保留在桌面应用程序项目中。

示例:将数据访问代码迁移到 .NET Standard 2.0 库

假设我们有一个非常基本的 Windows 窗体应用程序,用于显示 Northwind 示例数据库中的客户。

Windows 窗体应用

该项目包含一个 .NET Standard 2.0 类库,其静态类名为 Northwind。 如果将此代码移动到 Northwind 类中,则它不会编译,因为它使用 SQLConnectionSqlCommandSqlDataReader 类,以及 .NET Standard 2.0 中不可用的类。

public static ArrayList GetCustomerNames()
{
    ArrayList customers = new ArrayList();

    using (SqlConnection conn = new SqlConnection())
    {
        conn.ConnectionString = ...; // Your connection string goes here.

        conn.Open();

        SqlCommand command = new SqlCommand("select ContactName from customers order by ContactName asc", conn);

        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                customers.Add(reader[0]);
            }
        }
    }

    return customers;
}

不过,可以使用 .NET API 浏览器 查找替代方法。 DbConnectionDbCommandDbDataReader 类均在 .NET Standard 2.0 中可用,因此我们可以改用它们。

此修订的版本使用这些类来获取客户列表,但要创建 DbConnection 类,我们需要传入我们在客户端应用程序中创建的工厂对象。

public static ArrayList GetCustomerNames(DbProviderFactory factory)
{
    ArrayList customers = new ArrayList();

    using (DbConnection conn = factory.CreateConnection())
    {
        conn.ConnectionString = ...; // Your connection string goes here.

        conn.Open();

        DbCommand command = factory.CreateCommand();
        command.Connection = conn;
        command.CommandText = "select ContactName from customers order by ContactName asc";

        using (DbDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                customers.Add(reader[0]);
            }
        }
    }

    return customers;
}

在 Windows 窗体的代码隐藏页中,我们只需创建工厂实例并将其传递到方法中。

public partial class Customers : Form
{
    public Customers()
    {
        InitializeComponent();

        dataGridView1.Rows.Clear();

        SqlClientFactory factory = SqlClientFactory.Instance;

        foreach (string customer in Northwind.GetCustomerNames(factory))
        {
            dataGridView1.Rows.Add(customer);
        }
    }
}

创建 UWP 应用

现在,你已准备好将 UWP 应用添加到解决方案。

桌面到 UWP 桥映像

你仍然需要在 XAML 中设计 UI 页面并编写任何设备或平台特定的代码,但完成后,你将能够覆盖到 Windows 10 和 Windows 11 的所有设备,并使你的应用页面具有能够适应不同屏幕大小和分辨率的现代感。

你的应用程序将支持除键盘和鼠标之外的其他输入方式,且其功能和设置在各个设备上均易于使用。 这意味着用户一次了解如何执行操作,然后无论设备如何,它都以非常熟悉的方式工作。

这只是 UWP 附带的一些好处。 若要了解详细信息,请参阅 使用 Windows打造出色的体验。

添加 UWP 项目

首先,将 UWP 项目添加到解决方案。

UWP 项目

然后,从 UWP 项目中添加对 .NET Standard 2.0 库项目的引用。

UWP 解决方案资源管理器窗格的屏幕截图,其中突出显示了对 .NET 项目类库引用的调用。

构建你的页面

添加 XAML 页面并调用 .NET Standard 2.0 库中的代码。

UWP 应用

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel x:Name="customerStackPanel">
        <ListView x:Name="customerList"/>
    </StackPanel>
</Grid>
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        SqlClientFactory factory = SqlClientFactory.Instance;

        customerList.ItemsSource = Northwind.GetCustomerNames(factory);
    }
}

若要开始使用 UWP,请参阅 什么是 UWP 应用

后续步骤

查找问题答案

有疑问? 在 Stack Overflow 上询问我们。 我们的团队监视这些 标记。 还可以在此处 询问我们。