Migration de l’interface utilisateur (y compris WinUI 3)

Cette rubrique explique comment migrer le code de votre interface utilisateur, y compris la migration vers WinUI 3.

Résumé des différences d’API et/ou de fonctionnalités

La propriété Window.Current migre vers App.Window. Et la méthode CoreDispatcher.RunAsync migre vers DispatcherQueue.TryEnqueue.

Vous devez définir votre handle de fenêtre (HWND) sur un MessageDialog et sur des Sélecteurs.

Pour utiliser les API DataTransferManager, vous devez les associer à votre fenêtre.

Pour ContentDialog et Popup, vous devez définir leur propriété XamlRoot.

Il vous faudra peut-être refactoriser votre Visual State Manager et le balisage XAML Page.Resources.

Dans le SDK d’application Windows, AcrylicBrush échantillonne toujours du contenu de l’application.

Modifiez Windows.UI.Xaml.Window.Current pour App.Window

Cette section s’applique si vous utilisez la propriété Windows.UI.Xaml.Window.Current dans votre application UWP. Cette propriété n’étant pas prise en charge dans le SDK d’application Windows, cette section décrit comment porter du code UWP qui utilise Window.Current.

// MainPage.xaml.cs in a UWP app
var width = Window.Current.Bounds.Width;
// MainPage.xaml.cpp in a UWP app
auto width{ Window::Current().Bounds().Width };

Votre application SDK d’application Windows peut ajouter sa propre notion d’une fenêtre active ou principale à l’aide d’une propriété statique publique sur votre classe App.

// App.xaml.cs in a Windows App SDK app
public partial class App : Application
{
    ...
    public static Window Window { get { return m_window; } }
    private static Window m_window;
}
// App.xaml.h in a Windows App SDK app
...
struct App : AppT<App>
{
    ...
    static winrt::Microsoft::UI::Xaml::Window Window(){ return window; };

private:
    static winrt::Microsoft::UI::Xaml::Window window;
};
...

// App.xaml.cpp
...
winrt::Microsoft::UI::Xaml::Window App::window{ nullptr };
...

Ensuite, dans la propre classe App, vous pouvez remplacer Window.Current par simplement window. En dehors de la classe App, remplacez Window.Current par App.Window de la manière suivante :

// MainPage.xaml.cs in a UWP app
var width = App.Window.Bounds.Width;
// MainPage.xaml.cpp in a UWP app
#include <App.xaml.h>
auto width{ App::Window().Bounds().Width };

MessageDialog et Sélecteurs

Dans votre application UWP, si vous utilisez certains types à partir des espaces de noms Windows.UI.Popups ou Windows.Storage.Pickers, cette section contient des informations pour vous aider à migrer ce code. Les exemples de code ci-dessous utilisent MessageDialog, mais vous pouvez appliquer exactement les mêmes techniques pour afficher un sélecteur (par exemple, un FileOpenPicker, un FileSavePicker ou un FolderPicker).

Les étapes que vous devez suivre dans une application de bureau sont décrites dans Afficher les objets d’interface utilisateur WinRT qui dépendent de CoreWindow.

Remarque

Pour les nouvelles applications, nous vous recommandons d’utiliser le contrôle ContentDialog plutôt que MessageDialog. Pour plus d’informations, consultez la section ContentDialog et Popup ci-dessous.

Voici un code UWP classique pour afficher un MessageDialog.

// In a UWP app
var showDialog = new Windows.UI.Popups.MessageDialog("Message here");
await showDialog.ShowAsync();
// In a UWP app
auto showDialog{ Windows::UI::Popups::MessageDialog(L"Message here") };
co_await showDialog.ShowAsync();

Et voici le code équivalent dans une application SDK d’application Windows.

// MainWindow.xaml.cs in a WinUI 3 app
var showDialog = new Windows.UI.Popups.MessageDialog("Message here");
WinRT.Interop.InitializeWithWindow.Initialize(showDialog,
    WinRT.Interop.WindowNative.GetWindowHandle(this));
await showDialog.ShowAsync();
// pch.h in a WinUI 3 app
...
#include <Shobjidl.h>
#include <microsoft.ui.xaml.window.h>
#include <winrt/Windows.UI.Popups.h>
...

// MainWindow.xaml.cpp
...
auto showDialog{ Windows::UI::Popups::MessageDialog(L"Message here") };

auto windowNative{ this->m_inner.as<::IWindowNative>() };
HWND hWnd{ 0 };
windowNative->get_WindowHandle(&hWnd);
showDialog.as<::IInitializeWithWindow>()->Initialize(hWnd);

co_await showDialog.ShowAsync();

DataTransferManager

Dans votre application UWP, si vous appelez la méthode DataTransferManager.ShowShareUI, cette section contient des informations pour vous aider à migrer ce code.

Voici un code UWP classique qui appelle ShowShareUI.

// In a UWP app
var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView();

dataTransferManager.DataRequested += (sender, args) =>
{
    args.Request.Data.Properties.Title = "In a UWP app...";
    args.Request.Data.SetText("...display the user interface for sharing content with another app.");
    args.Request.Data.RequestedOperation =
        Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;
};

Windows.ApplicationModel.DataTransfer.DataTransferManager.ShowShareUI();
// In a UWP app
#include <winrt/Windows.ApplicationModel.DataTransfer.h>
...
auto dataTransferManager{ Windows::ApplicationModel::DataTransfer::DataTransferManager::GetForCurrentView() };

dataTransferManager.DataRequested([](Windows::ApplicationModel::DataTransfer::DataTransferManager const& /* sender */,
    Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs const& args)
    {
        args.Request().Data().Properties().Title(L"In a UWP app...");
        args.Request().Data().SetText(L"...display the user interface for sharing content with another app.");
        args.Request().Data().RequestedOperation(Windows::ApplicationModel::DataTransfer::DataPackageOperation::Copy);
    });

Windows::ApplicationModel::DataTransfer::DataTransferManager::ShowShareUI();

Pour utiliser DataTransferManager.ShowShareUI dans votre application SDK d’application Windows, vous devez associer l’interface utilisateur de partage à votre fenêtre. Et cela doit être fait manuellement. Pour plus d’informations et pour obtenir des exemples de code, consultez Afficher les objets d’interface utilisateur WinRT qui dépendent de CoreWindow.

ContentDialog et Popup

Dans votre application UWP, si vous utilisez les classes Windows.UI.Xaml.Controls.ContentDialog ou Windows.UI.Xaml.Controls.Primitives.Popup, cette section contient des informations pour vous aider à migrer ce code. Les exemples de code ci-dessous utilisent ContentDialog, mais vous pouvez appliquer exactement les mêmes techniques pour afficher un objet Popup.

Voici un code UWP classique pour afficher un ContentDialog.

// MainPage.xaml.cs in a UWP app
var unsupportedFilesDialog = new ContentDialog();
// Set Title, Content, etc.
await unsupportedFilesDialog.ShowAsync();
// MainPage.xaml.cpp in a UWP app
ContentDialog unsupportedFilesDialog{};
// Set Title, Content, etc.
co_await unsupportedFilesDialog.ShowAsync();

Dans votre application SDK d’application Windows, vous devez simplement définir la propriété XamlRoot de la boîte de dialogue. Voici comment procéder.

// MainPage.xaml.cs in a Windows App SDK app
var unsupportedFilesDialog = new ContentDialog();
// Set Title, Content, etc.
unsupportedFilesDialog.XamlRoot = this.Content.XamlRoot;
await unsupportedFilesDialog.ShowAsync();
// MainPage.xaml.cpp in a Windows App SDK app
ContentDialog unsupportedFilesDialog{};
// Set Title, Content, etc.
unsupportedFilesDialog.XamlRoot(this->Content().XamlRoot());
co_await unsupportedFilesDialog.ShowAsync();

Dois-je implémenter la navigation de page ?

Dans un projet UWP, par défaut, il y aura du code de navigation dans les méthodes de la classe App, même si votre application est tellement simple qu’elle ne possède qu’une seule page.

Quand vous créez un projet de SDK d’application Windows dans Visual Studio, le modèle de projet vous fournit une classe MainWindow (de type Microsoft.UI.Xaml.Window), mais aucune Page. En outre, le modèle de projet ne fournit aucun code de navigation.

Pour une application SDK d’application Windows relativement simple (à une seule page), vous pouvez peut-être le simplifier. Il se peut que vous n’ayez pas besoin de créer de pages ou de contrôles utilisateur dans votre projet SDK d’application Windows, et qu'il vous suffise de copier le balisage XAML et le code-behind de cette page unique dans MainWindow. Il y a cependant plusieurs choses que MainWindow ne prend pas en charge. Window n’est pas un DependencyObject, ce qui signifie qu'il ne dispose pas de fonctionnalités comme Resources et DataContext, ni d'événements comme Load et Unload. Pour en savoir plus et obtenir des solutions de contournement, reportez-vous à Visual State Manager et Page.Resources.

En revanche, si vous souhaitez ou avez besoin de naviguer entre les pages de votre application SDK d’application Windows, vous pouvez le faire en migrant les méthodes App.OnLaunched et App ::OnNavigationFailed à partir de votre application UWP. Dans App.OnLaunched, localisez le code de navigation (le code qui crée rootFrame, puis navigue jusqu'à la première page de votre application) et fusionnez-le directement entre les deux lignes de code existantes (les lignes qui créent une fenêtre, puis l'activent). Vous devez également migrer le code que vous avez copié-collé. Pour obtenir un exemple de code simple, consultez la classe Page.

Visual State Manager et Page.Resources

Consultez également Faut-il implémenter la navigation dans les pages ?. Si vous avez une application UWP qui est suffisamment simple pour que vous puissiez copier votre balisage XAML et votre code-behind dans MainWindow, gardez à l’esprit ces exceptions.

Votre classe MainWindow (de type Microsoft.UI.Xaml.Window) n’est pas un contrôle. Elle ne prend donc pas en charge le balisage XAML Visual State Manager ni le code-behind (voir Didacticiel : Créer des dispositions adaptatives). Quoi qu'il en soit, vous avez deux options :

  • Ajoutez un élément UserControl au projet, migrez votre balisage et votre code-behind vers celui-ci, puis placez une instance de ce contrôle utilisateur dans MainWindow.
  • Ajoutez un élément Page au projet, migrez votre balisage et votre code-behind vers celui-ci, puis ajoutez du code à votre classe App pour accéder à cette Page au démarrage, conformément aux indications de Faut-il implémenter la navigation dans les pages ?.

D'autre part, il n'est pas possible de copier un élément <Page.Resources> dans MainWindow et de le renommer simplement <Window.Resources>. Il vous faudra placer l’élément Resources comme parent sous le conteneur racine (par exemple, une Grille) dans le balisage XAML pour MainWindow, de la manière suivante :

<Window ...>
    <Grid>
        <Grid.Resources>...</Grid.Resources>
        ...
    </Grid>
</Window>

AcrylicBrush.BackgroundSource property

La propriété AcrylicBrush.BackgroundSource existe dans UWP, mais pas dans le SDK d’application Windows. Dans le SDK d’application Windows, AcrylicBrush échantillonne toujours du contenu de l’application.

Par conséquent, si vous accédez à la propriété AcrylicBrush.BackgroundSource dans le code source de votre application UWP (que ce soit dans le balisage XAML ou dans le code impératif), supprimez ce code lorsque vous migrez votre application vers le SDK d’application Windows. Utilisez plutôt la classe DesktopAcrylicController.