Estendere l'app desktop con componenti UWP moderni
Alcune esperienze di Windows (ad esempio una pagina dell'interfaccia utente abilitata per il tocco) devono essere eseguite all'interno di un contenitore di app. Se si desidera aggiungere queste esperienze, estendere l'applicazione desktop con progetti UWP e componenti Windows Runtime.
In molti casi è possibile chiamare le API di Windows Runtime direttamente dall'applicazione desktop, pertanto prima di continuare la lettura, vedere Migliorare per Windows.
Nota
Le funzionalità descritte in questo argomento richiedono che venga creato un pacchetto dell'app (con identità del pacchetto al momento del runtime). Sono incluse le app in pacchetto (vedere Creare un nuovo progetto per un'app desktop WinUI 3 in pacchetto) e le app in pacchetto con posizione esterna (vedere Concedere identità del pacchetto creando pacchetti con posizione esterna). Vedere anche Funzionalità che richiedono l'identità del pacchetto.
Innanzitutto configura la soluzione
Aggiungi uno o più componenti di runtime e progetti UWP alla tua soluzione.
Inizia con una soluzione che contiene un Progetto di creazione pacchetti per applicazioni Windows con un riferimento all'applicazione desktop.
Questa immagine mostra una soluzione di esempio.
Se la soluzione non contiene un progetto di creazione di pacchetti, vedi Creare un pacchetto dell'applicazione desktop con Visual Studio.
Configurare l'applicazione desktop
Assicurati che l'applicazione desktop includa riferimenti ai file necessari per chiamare le API di Windows Runtime.
A tale scopo, vedi Chiamare le API di Windows Runtime nelle app desktop.
Aggiungere un progetto UWP
Aggiungi un progetto App vuota (Universale di Windows) alla soluzione.
Qui compilerai un'interfaccia utente XAML moderna o userai API che vengono eseguite solo in un processo UWP.
Nel progetto di creazione di pacchetti fai clic con il pulsante destro del mouse sul nodo Applicazioni e quindi fai clic su Aggiungi riferimento.
Quindi, aggiungi un riferimento al progetto UWP.
La soluzione avrà un aspetto simile al seguente:
(Facoltativo) Aggiungere un componente Windows Runtime
Per eseguire alcuni scenari, è necessario aggiungere codice a un componente Windows Runtime.
Quindi, dal progetto UWP aggiungi un riferimento al componente di runtime. La soluzione avrà un aspetto simile al seguente:
Compilare la soluzione
Compila la soluzione per assicurarti che non vengano visualizzati errori. Se vengono visualizzati errori, apri Gestione configurazione e verifica che i progetti siano destinati alla stessa piattaforma.
Vediamo cosa puoi fare con i progetti UWP e i componenti di runtime.
Visualizzare un'interfaccia utente XAML moderna
Durante il flusso dell'applicazione, puoi incorporare le interfacce utente moderne basate su XAML nell'applicazione desktop. Queste interfacce utente sono naturalmente adattive a diverse risoluzioni e dimensioni dello schermo e supportano i moderni modelli interattivi, ad esempio il tocco e l'input penna.
Con poche righe di markup XAML, ad esempio, puoi concedere agli utenti efficaci funzionalità di visualizzazione correlate alla mappa.
Questa immagine mostra un'applicazione Windows Forms che apre un'interfaccia utente moderna basata su XAML che contiene un controllo mappa.
Nota
Questo esempio mostra un'interfaccia utente XAML con l'aggiunta di un progetto UWP alla soluzione. Questo è l'approccio supportato stabile per visualizzare le interfacce utente XAML in un'applicazione desktop. L'alternativa a questo approccio consiste nell'aggiungere controlli XAML UWP direttamente all'applicazione desktop usando un'isola XAML. Le isole XAML sono attualmente disponibili come anteprima per sviluppatori. Ti invitiamo a provarli nel codice prototipo, ma per il momento ti consigliamo di non usarli nel codice di produzione. Queste API e controlli continueranno a evolversi e a stabilizzarsi nelle versioni future di Windows. Per altre informazioni sulle isole XAML, vedi Controlli UWP nelle applicazioni desktop
Pattern di progettazione
Per visualizzare un'interfaccia utente basata su XAML, esegui queste operazioni:
2️⃣ Creare un'interfaccia utente XAML
3️⃣ Aggiungere un'estensione del protocollo al progetto UWP
4️⃣ Avviare l'app UWP dall'app desktop
5️⃣ Nel progetto UWP, visualizzare la pagina desiderata
Configurare la soluzione
Per informazioni generali su come configurare la soluzione, vedere la sezione Configurare la soluzione come primo passo all'inizio di questa guida.
La soluzione avrà un aspetto simile al seguente:
In questo esempio il progetto Windows Forms è denominato Landmarks e il progetto UWP che contiene l'interfaccia utente XAML è denominato MapUI.
Creare un'interfaccia utente XAML
Aggiungi un'interfaccia utente XAML al progetto UWP. Ecco il codice XAML per una mappa di base.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="12,20,12,14">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<maps:MapControl x:Name="myMap" Grid.Column="0" Width="500" Height="500"
ZoomLevel="{Binding ElementName=zoomSlider,Path=Value, Mode=TwoWay}"
Heading="{Binding ElementName=headingSlider,Path=Value, Mode=TwoWay}"
DesiredPitch="{Binding ElementName=desiredPitchSlider,Path=Value, Mode=TwoWay}"
HorizontalAlignment="Left"
MapServiceToken="<Your Key Goes Here" />
<Grid Grid.Column="1" Margin="12">
<StackPanel>
<Slider Minimum="1" Maximum="20" Header="ZoomLevel" Name="zoomSlider" Value="17.5"/>
<Slider Minimum="0" Maximum="360" Header="Heading" Name="headingSlider" Value="0"/>
<Slider Minimum="0" Maximum="64" Header=" DesiredPitch" Name="desiredPitchSlider" Value="32"/>
</StackPanel>
</Grid>
</Grid>
Aggiungere un'estensione del protocollo
In Esplora soluzioni apri il file package.appxmanifest del progetto di creazione pacchetti nella soluzione e aggiungi questa estensione.
<Extensions>
<uap:Extension Category="windows.protocol" Executable="MapUI.exe" EntryPoint="MapUI.App">
<uap:Protocol Name="xamluidemo" />
</uap:Extension>
</Extensions>
Assegna un nome al protocollo, specifica il nome del file eseguibile generato dal progetto UWP e il nome della classe del punto di ingresso.
Puoi anche aprire package.appxmanifest nella finestra di progettazione, scegliere la scheda Dichiarazioni e quindi aggiungere l'estensione.
Nota
La mappa controlla il download dei dati da Internet in modo che se ne fai uso, dovrai aggiungere anche la funzionalità "client Internet" al manifesto.
Avviare l'app UWP
Prima di tutto, dall'applicazione desktop crea un Uri che include il nome del protocollo ed eventuali parametri da passare all'app UWP. Chiama quindi il metodo LaunchUriAsync.
private void Statue_Of_Liberty_Click(object sender, EventArgs e)
{
ShowMap(40.689247, -74.044502);
}
private async void ShowMap(double lat, double lon)
{
string str = "xamluidemo://";
Uri uri = new Uri(str + "location?lat=" +
lat.ToString() + "&?lon=" + lon.ToString());
var success = await Windows.System.Launcher.LaunchUriAsync(uri);
}
Analizzare i parametri e visualizzare una pagina
Nella classe App del progetto UWP esegui l'override del gestore eventi OnActivated. Se l'app viene attivata dal protocollo, analizza i parametri e quindi apri la pagina desiderata.
protected override void OnActivated(Windows.ApplicationModel.Activation.IActivatedEventArgs e)
{
if (e.Kind == ActivationKind.Protocol)
{
ProtocolActivatedEventArgs protocolArgs = (ProtocolActivatedEventArgs)e;
Uri uri = protocolArgs.Uri;
if (uri.Scheme == "xamluidemo")
{
Frame rootFrame = new Frame();
Window.Current.Content = rootFrame;
rootFrame.Navigate(typeof(MainPage), uri.Query);
Window.Current.Activate();
}
}
}
Nel codice sottostante la pagina XAML esegui l'override del metodo OnNavigatedTo
per usare i parametri passati nella pagina. In questo caso useremo la latitudine e la longitudine passate in questa pagina per mostrare una posizione su una mappa.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.Parameter != null)
{
WwwFormUrlDecoder decoder = new WwwFormUrlDecoder(e.Parameter.ToString());
double lat = Convert.ToDouble(decoder[0].Value);
double lon = Convert.ToDouble(decoder[1].Value);
BasicGeoposition pos = new BasicGeoposition();
pos.Latitude = lat;
pos.Longitude = lon;
myMap.Center = new Geopoint(pos);
myMap.Style = MapStyle.Aerial3D;
}
base.OnNavigatedTo(e);
}
Rendere l'applicazione desktop una destinazione di condivisione
Puoi rendere la tua applicazione desktop una destinazione di condivisione in modo che gli utenti possano condividere facilmente dati come immagini da altre app che supportano la condivisione.
Ad esempio, gli utenti potrebbero scegliere la tua applicazione per condividere le immagini da Microsoft Edge, l'app Foto. Ecco un'applicazione WPF di esempio con questa funzionalità.
.
Vedi l'esempio completo qui
Pattern di progettazione
Per rendere l'applicazione una destinazione di condivisione, esegui queste operazioni:
1️⃣ Aggiungere un'estensione di destinazione di condivisione
2️⃣ Eseguire l'override del gestore eventi OnShareTargetActivated
3️⃣ Aggiungere le estensioni desktop al progetto UWP
4️⃣ Aggiungere l'estensione del processo di attendibilità totale
5️⃣ Modificare l'applicazione desktop per ottenere il file condiviso
Passaggi seguenti
Aggiungere un'estensione di destinazione di condivisione
In Esplora soluzioni apri il file package.appxmanifest del progetto di creazione pacchetti nella soluzione e aggiungi l'estensione di destinazione di condivisione.
<Extensions>
<uap:Extension
Category="windows.shareTarget"
Executable="ShareTarget.exe"
EntryPoint="App">
<uap:ShareTarget>
<uap:SupportedFileTypes>
<uap:SupportsAnyFileType />
</uap:SupportedFileTypes>
<uap:DataFormat>Bitmap</uap:DataFormat>
</uap:ShareTarget>
</uap:Extension>
</Extensions>
Specifica il nome del file eseguibile generato dal progetto UWP e il nome della classe del punto di ingresso. Questo markup presuppone che il nome del file eseguibile per l'app UWP sia ShareTarget.exe
.
Dovrai anche specificare quali tipi di file possono essere condivisi con la tua app. In questo esempio stiamo rendendo l'applicazione desktop WPF PhotoStoreDemo una destinazione di condivisione per le immagini bitmap, quindi specifichiamo Bitmap
per il tipo di file supportato.
Eseguire l'override del gestore eventi OnShareTargetActivated
Esegui l'override del gestore eventi OnShareTargetActivated nella classe App del progetto UWP.
Questo gestore eventi viene chiamato quando gli utenti scelgono la tua app per condividere i file.
protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
shareWithDesktopApplication(args.ShareOperation);
}
private async void shareWithDesktopApplication(ShareOperation shareOperation)
{
if (shareOperation.Data.Contains(StandardDataFormats.StorageItems))
{
var items = await shareOperation.Data.GetStorageItemsAsync();
StorageFile file = items[0] as StorageFile;
IRandomAccessStreamWithContentType stream = await file.OpenReadAsync();
await file.CopyAsync(ApplicationData.Current.LocalFolder);
shareOperation.ReportCompleted();
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
}
}
In questo codice abbiamo salvato l'immagine che viene condivisa dall'utente in una cartella di archiviazione locale delle app. Successivamente, l'applicazione desktop verrà modificata per eseguire il pull delle immagini dalla stessa cartella. L'applicazione desktop può eseguire questa operazione perché è inclusa nello stesso pacchetto dell'app UWP.
Aggiungere le estensioni desktop al progetto UWP
Aggiungere l'estensione Windows Desktop Extensions for the UWP al progetto di app UWP. Si vedrà più di una versione dell'estensione (ad esempio, 10.0.18362.0 e 10.0.19041.0). Per informazioni su come scegliere una versione, vedere SDK estensione e come farvi riferimento.
Aggiungere l'estensione del processo di attendibilità totale
In Esplora soluzioni apri il file package.appxmanifest del progetto di creazione pacchetti nella soluzione e quindi aggiungi l'estensione del processo di attendibilità totale accanto all'estensione di condivisione della destinazione aggiunta in precedenza a questo file.
<Extensions>
...
<desktop:Extension Category="windows.fullTrustProcess" Executable="PhotoStoreDemo\PhotoStoreDemo.exe" />
...
</Extensions>
Questa estensione consentirà all'app UWP di avviare l'applicazione desktop con cui vuoi condividere un file. Nell'esempio facciamo riferimento al file eseguibile dell'applicazione desktop WPF PhotoStoreDemo.
Modificare l'applicazione desktop per ottenere il file condiviso
Modifica l'applicazione desktop per trovare ed elaborare il file condiviso. In questo esempio l'app UWP ha archiviato il file condiviso nella cartella dei dati locali dell'app. Pertanto, modificheremo l'applicazione desktop WPF PhotoStoreDemo per eseguire il pull delle foto da tale cartella.
Photos.Path = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
Per le istanze dell'applicazione desktop già aperte dall'utente, è anche possibile gestire l'evento FileSystemWatcher e passare il percorso in cui si trova il file. In questo modo, tutte le istanze aperte dell'applicazione desktop visualizzeranno la foto condivisa.
...
FileSystemWatcher watcher = new FileSystemWatcher(Photos.Path);
...
private void Watcher_Created(object sender, FileSystemEventArgs e)
{
// new file got created, adding it to the list
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
{
if (File.Exists(e.FullPath))
{
ImageFile item = new ImageFile(e.FullPath);
Photos.Insert(0, item);
PhotoListBox.SelectedIndex = 0;
CurrentPhoto.Source = (BitmapSource)item.Image;
}
}));
}
Creare un'attività in background
Aggiungi un'attività in background per eseguire il codice anche quando l'app viene sospesa. Le attività in background sono ideali per le piccole attività che non richiedono l'interazione dell'utente. Ad esempio, l'attività può scaricare la posta, visualizzare una notifica di tipo avviso popup su un messaggio di chat in ingresso o rispondere a una modifica in una condizione di sistema.
Ecco un'applicazione di esempio WPF che registra un'attività in background.
L'attività crea una richiesta http e misura il tempo che la richiesta impiega per restituire una risposta. Le tue attività saranno probabilmente più interessanti, ma questo esempio è ideale per imparare il funzionamento di base di un'attività in background.
Vedi l'esempio completo qui.
Pattern di progettazione
Per creare un servizio in background, esegui queste operazioni:
1️⃣ Implementare l'attività in background
2️⃣ Configurare l'attività in background
3️⃣ Registrare l'attività in background
Implementare l'attività in background
Implementa l'attività in background mediante l'aggiunta di codice a un progetto di componente Windows Runtime.
public sealed class SiteVerifier : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.Canceled += TaskInstance_Canceled;
BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
var msg = await MeasureRequestTime();
ShowToast(msg);
deferral.Complete();
}
private async Task<string> MeasureRequestTime()
{
string msg;
try
{
var url = ApplicationData.Current.LocalSettings.Values["UrlToVerify"] as string;
var http = new HttpClient();
Stopwatch clock = Stopwatch.StartNew();
var response = await http.GetAsync(new Uri(url));
response.EnsureSuccessStatusCode();
var elapsed = clock.ElapsedMilliseconds;
clock.Stop();
msg = $"{url} took {elapsed.ToString()} ms";
}
catch (Exception ex)
{
msg = ex.Message;
}
return msg;
}
Configurare l'attività in background
In Progettazione manifesto apri il file package.appxmanifest del progetto di creazione pacchetti nella soluzione.
Nella scheda Dichiarazioni aggiungi una dichiarazione Attività in background.
Quindi, scegli le proprietà desiderate. Il nostro esempio usa la proprietà Timer.
Specifica il nome completo della classe nel componente Windows Runtime che implementa l'attività in background.
Registrare l'attività in background
Aggiungi il codice al progetto di applicazione desktop che registra l'attività in background.
public void RegisterBackgroundTask(String triggerName)
{
var current = BackgroundTaskRegistration.AllTasks
.Where(b => b.Value.Name == triggerName).FirstOrDefault().Value;
if (current is null)
{
BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
builder.Name = triggerName;
builder.SetTrigger(new MaintenanceTrigger(15, false));
builder.TaskEntryPoint = "HttpPing.SiteVerifier";
builder.Register();
System.Diagnostics.Debug.WriteLine("BGTask registered:" + triggerName);
}
else
{
System.Diagnostics.Debug.WriteLine("Task already:" + triggerName);
}
}
Trova le risposte alle tue domande
Altre domande? Partecipa a Stack Overflow. Il nostro team controlla costantemente questi tag. Puoi inviarci le tue domande anche qui.