Migrazione dell'interfaccia utente (incluso WinUI 3)
Questo argomento illustra come eseguire la migrazione del codice dell'interfaccia utente, incluso WinUI 3.
Riepilogo delle differenze tra API e/o funzionalità
La proprietà Window.Current esegue la migrazione ad App.Window. E il metodo CoreDispatcher.RunAsync esegue la migrazione a DispatcherQueue.TryEnqueue.
Occorre impostare l'handle (HWND) della finestra su un MessageDialog e su Pickers.
Per utilizzare le API DataTransferManager, è necessario associarle alla finestra.
Per ContentDialog e Popup, occorre impostane la proprietà XamlRoot.
Potrebbe essere necessario eseguire il refactoring del Visual State Manager e del markup XAML di Page.Resources.
In Windows App SDK, AcrylicBrush prende sempre esempi dal contenuto dell'app.
Modificare Windows.UI.Xaml.Window.Current in App.Window
Questa sezione si applica se si utilizza la proprietà Windows.UI.Xaml.Window.Current nell'app UWP. Questa proprietà non è supportata in Windows App SDK, perciò questa sezione descrive come convertire il codice UWP che utilizza 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 };
L'app Windows App SDK può aggiungere la propria nozione di una finestra attuale o principale usando una proprietà statica pubblica nella 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 };
...
Quindi, all'interno della stessa classe App, è possibile modificare Window.Current
semplicemente in window
. Al di fuori della classe App, modificare Window.Current
in App.Window
, in questo modo:
// 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 e Selettori
Nell'app UWP, se si utilizzano certi tipi di spazi di nomi Windows.UI.Popups o Windows.Storage.Pickers, questa sezione contiene informazioni utili alla migrazione di quel codice. Gli esempi di codice seguenti utilizzano MessageDialog, ma si possono applicare le stesse identiche tecniche per visualizzare un selettore (ad esempio un FileOpenPicker, un FileSavePicker o un FolderPicker).
I passaggi da seguire in un'app desktop sono descritti in Visualizzare gli oggetti dell'interfaccia utente WinRT che dipendono da CoreWindow.
Nota
Per le nuove app, consigliamo di utilizzare ContentDialog anziché MessageDialog. Per altre informazioni, vedere la sezione ContentDialog e Popup di seguito.
Ecco un tipico codice UWP per visualizzare 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();
Ed ecco lo stesso codice in un'app Windows App SDK.
// 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
Nell'app UWP, se si chiama il metodo DataTransferManager.ShowShareUI, questa sezione contiene informazioni utili alla migrazione di quel codice.
Ecco un tipico codice UWP che chiama 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();
Per utilizzare DataTransferManager.ShowShareUI nell'app Windows App SDK, è necessario devi associare l'interfaccia utente condivisa con la finestra. Questa operazione deve essere eseguita manualmente. Per altre informazioni ed esempi di codice, vedere Visualizzazione di oggetti WinRT Ui che dipendono da CoreWindow.
ContentDialog e Popup
Se nell'app UWP si usano le classi Windows.UI.Xaml.Controls.ContentDialog o Windows.UI.Xaml.Controls.Primitives.Popup, questa sezione contiene informazioni utili alla migrazione di quel codice. Gli esempi di codice seguenti usano ContentDialog, ma si possono applicare le stesse identiche tecniche per visualizzare un oggetto Popup.
Ecco un tipico codice UWP per visualizzare 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();
Nell'app Windows App SDK, è sufficiente impostare la proprietà XamlRoot del dialogo. Ecco come.
// 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();
Devo implementare lo spostamento nella pagina?
In un progetto UWP, ci sarà per impostazione predefinita un codice di spostamento nei metodi della classe App, anche se l'app è così semplice da avere una sola Pagina.
Quando si crea un nuovo progetto Windows App SDK in Visual Studio, il modello di progetto fornisce una classe MainWindow (di tipo Microsoft.UI.Xaml.Window), ma nessuna Pagina. E il modello di progetto non fornisce alcun codice di spostamento.
Per un'app Windows App SDK sufficientemente semplice (app di una sola pagina), potresti semplificarla. Potrebbe non essere necessario creare pagine o controlli utenti nel progetto Windows App SDK; bisogna copiare piuttosto il markup XAML e il code-behind di quella singola pagina nella MainWindow. Ci sono però alcune cose che MainWindow non supporta. Window non è un DependencyObject, quindi funzionalità quali Risorse e DataContext non vi esistono. E nemmeno eventi quali Carica e Scarica. Per altre informazioni e soluzioni alternative, vedere Visual State Manager e Page.Resources.
Se invece si vuole o è necessario lo spostamento tra le pagine nell'app Windows App SDK, è possibile aggiungerla eseguendo la migrazione dei metodi App.OnLaunched e App::OnNavigationFailed dall'app UWP. In App.OnLaunched individuare il codice di spostamento (il codice che crea rootFrame e passa alla prima pagina dell'app) e unirlo direttamente tra le due righe di codice esistenti (le righe che creano una finestra e quindi la attivano). Sarà necessario eseguire la migrazione anche del codice copiato e incollato. Per un semplice esempio di codice, vedere Classe di Pagina.
Visual State Manager e Page.Resources
Vedere anche Devo implementare lo spostamento nella pagina?. Se si ha un'app UWP sufficientemente semplice dove è possibile copiare il markup XAML e il code-behind in MainWindow, tenere presenti queste eccezioni.
La classe MainWindow (di tipo Microsoft.UI.Xaml.Window) non è un controllo, quindi non supporta il markup XAML e il code-behind di Visual State Manager (vedere Esercitazione: creare layout adattivi). Esistono comunque queste due opzioni:
- Aggiungere un elemento UserControl al progetto ed eseguirvi la migrazione del markup e del code-behind. Inserire quindi un'istanza di quel controllo utente in MainWindow.
- Aggiungere un elemento Page al progetto ed eseguirvi la migrazione del markup e del code-behind. Aggiungere quindi il codice alla classe App per lo spostamento su quella Page all'avvio, come descritto in Devo implementare lo spostamento nella pagina?.
Inoltre, non sarà possibile copiare un elemento <Page.Resources>
su MainWindow e rinominarlo semplicemente <Window.Resources>
. Associare invece l'elemento Risorse sotto al contenitore root di layout (ad esempio una Griglia) nel markup XAML per MainWindow. Il risultato sarà simile al seguente:
<Window ...>
<Grid>
<Grid.Resources>...</Grid.Resources>
...
</Grid>
</Window>
Proprietà AcrylicBrush.BackgroundSource
La proprietà AcrylicBrush.BackgroundSource esiste nella piattaforma UWP, ma non in Windows App SDK. In Windows App SDK, AcrylicBrush prende sempre esempi dal contenuto dell'app.
Perciò se si accede alla proprietà AcrylicBrush.BackgroundSource nel codice sorgente dell'app UWP (che sia in markup XAML o in codice imperativo), occorre rimuovere quel codice quando si esegue la migrazione dell'app a Windows App SDK. Usare invece la classe DesktopAcrylicController.