Panoramica delle finestre WPF (WPF .NET)

Gli utenti interagiscono con le applicazioni Windows Presentation Foundation (WPF) tramite le finestre. Lo scopo principale di una finestra è ospitare contenuto tramite cui visualizzare dati e permettere agli utenti di interagire con i dati. Le applicazioni WPF forniscono finestre personalizzate usando la classe Window. Questo articolo presenta la classe Window prima di illustrare i concetti fondamentali della creazione e della gestione delle finestre nelle applicazioni.

Importante

Questo articolo usa il codice XAML generato da un progetto C#. Se si usa Visual Basic, il codice XAML potrebbe avere un aspetto leggermente diverso. Queste differenze sono in genere presenti nei valori dell'attributo x:Class. C# include lo spazio dei nomi radice per il progetto, che in Visual Basic è assente.

I modelli di progetto per C# creano un tipo App contenuto nel file app.xaml. In Visual Basic il tipo è denominato Application e il file è denominato Application.xaml.

Classe Window

In WPF una finestra è incapsulata dalla classe Window usata per eseguire queste operazioni:

  • Visualizzare una finestra.
  • Configurare dimensioni, posizione e aspetto di una finestra.
  • Ospitare contenuto specifico dell'applicazione.
  • Gestire la durata di una finestra.

La figura seguente mostra le parti che costituiscono una finestra:

Screenshot che mostra le parti di una finestra WPF.

Un finestra è suddivisa in due aree: l'area non client e l'area client.

L'area non client di una finestra viene implementata da WPF e include le parti di una finestra comuni alla maggior parte delle finestre, incluse le seguenti:

  • Una barra del titolo (1-5).
  • Un'icona (1).
  • Titolo (2).
  • Pulsanti Riduci a icona (3), Ingrandisci (4) e Chiudi (5).
  • Menu di sistema (6) con voci di menu. Viene visualizzato quando si fa clic sull'icona (1).
  • Bordo (7).

L'area client di una finestra è l'area all'interno di un'area non client e viene usata dagli sviluppatori per aggiungere il contenuto specifico dell'applicazione, come barre dei menu, barre degli strumenti e controlli.

  • Area client (8).
  • Barretta verticale di ridimensionamento (9). Si tratta di un controllo aggiunto all'area client (8).

Implementazione di una finestra

L'implementazione di una tipica finestra include l'aspetto e il comportamento, dove il termine aspetto definisce il modo in cui la finestra appare all'utente, mentre il termine comportamento indica il funzionamento di una finestra quando gli utenti interagiscono con essa. In WPF è possibile implementare l'aspetto e il comportamento di una finestra tramite codice o markup XAML.

In generale, tuttavia, l'aspetto di una finestra viene implementato usando il markup XAML, mentre il comportamento viene implementato tramite code-behind, come mostrato nell'esempio seguente.

<Window x:Class="WindowsOverview.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowsOverview"
        >

    <!-- Client area containing the content of the window -->
    
</Window>

Il codice seguente è il code-behind per il markup XAML.

using System.Windows;

namespace WindowsOverview
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}
Public Class Window1

End Class

Per poter usare un file di markup XAML e un file code-behind insieme, devono verificarsi le condizioni seguenti:

  • Nel markup l'elemento Window deve includere l'attributo x:Class. Quando viene compilata l'applicazione, se è presente l'attributo x:Class il motore di compilazione Microsoft (MSBuild) genera una classe partial che deriva da Window e il cui nome è specificato dall'attributo x:Class. Questa operazione richiede l'aggiunta di una dichiarazione dello spazio dei nomi XML per lo schema XAML (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"). La classe partial generata implementa il metodo InitializeComponent, che viene chiamato per registrare gli eventi e impostare le proprietà implementate nel markup.

  • Nel code-behind la classe deve essere una classe partial con lo stesso nome specificato dall'attributo x:Class nel markup e deve derivare da Window. In questo modo, il file code-behind può essere associato alla classe partial generata per il file di markup durante la compilazione dell'applicazione. Per altre informazioni, vedere Compilare un'applicazione WPF.

  • Nel code-behind la classe Window deve implementare un costruttore che chiama il metodo InitializeComponent. Il metodo InitializeComponent viene implementato dalla classe partial generata dal file di markup per registrare gli eventi e impostare le proprietà definite nel markup.

Nota

Quando si aggiunge una nuova classe Window al progetto usando Visual Studio, la classe Window viene implementata sia tramite il markup che il code-behind e include la configurazione necessaria per creare l'associazione tra il file di markup e il file code-behind, come descritto in questo argomento.

Con questa configurazione, è possibile concentrarsi sulla definizione dell'aspetto della finestra nel markup XAML e sull'implementazione del suo comportamento nel code-behind. Nell'esempio seguente viene illustrata una finestra con un pulsante che definisce un gestore eventi per l'evento Click. La finestra è implementata in XAML e il gestore è implementato nel code-behind.

<Window x:Class="WindowsOverview.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowsOverview"
        >

    <!-- Client area containing the content of the window -->

    <Button Click="Button_Click">Click This Button</Button>
    
</Window>

Il codice seguente è il code-behind per il markup XAML.

using System.Windows;

namespace WindowsOverview
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button was clicked.");
        }
    }
}
Public Class Window1

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        MessageBox.Show("Button was clicked.")
    End Sub

End Class

Configurazione di una finestra per MSBuild

Il modo in cui viene implementata la finestra ne determina la configurazione per MSBuild. Per una finestra definita tramite markup XAML e code-behind:

  • I file di markup XAML vengono configurati come elementi Page di MSBuild.
  • I file code-behind vengono configurati come elementi Compile di MSBuild.

I progetti .NET SDK importano automaticamente gli elementi Page e Compile corretti e non è necessario dichiararli. Quando il progetto è configurato per WPF, i file di markup XAML vengono importati automaticamente come elementi Page e il file code-behind corrispondente viene importato come Compile.

I progetti MSBuild non importano automaticamente i tipi ed è necessario dichiararli personalmente:

<Project>
    ...
    <Page Include="MarkupAndCodeBehindWindow.xaml" />
    <Compile Include=" MarkupAndCodeBehindWindow.xaml.cs" />
    ...
</Project>

Per informazioni sulla compilazione di applicazioni WPF, vedere Compilare un'applicazione WPF.

Durata di una finestra

Come con qualsiasi classe, una finestra ha una durata che inizia alla creazione della prima istanza, dopo la quale viene aperta, attivata e disattivata e infine chiusa.

Apertura di una finestra

Per aprire una finestra, è necessario prima di tutto crearne un'istanza, come mostrato nell'esempio seguente:

using System.Windows;

namespace WindowsOverview
{
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            // Create the window
            Window1 window = new Window1();

            // Open the window
            window.Show();
        }
    }
}
Class Application

    Private Sub Application_Startup(sender As Object, e As StartupEventArgs)
        ' Create the window
        Dim window As New Window1

        ' Open the window
        window.Show()
    End Sub

End Class

In questo esempio viene creata un'istanza di Window1 all'avvio dell'applicazione, che si verifica quando viene generato l'evento Startup. Per altre informazioni sulla finestra di avvio, vedere Come ottenere o impostare la finestra principale dell'applicazione.

Quando viene creata un'istanza di una finestra, un riferimento a essa viene aggiunto automaticamente a un elenco di finestre gestito dall'oggetto Application. La prima finestra di cui creare un'istanza viene impostata automaticamente dall'oggetto Application come finestra principale dell'applicazione.

La finestra viene infine aperta chiamando il metodo Show, come illustrato nell'immagine seguente:

Finestra WPF con un singolo pulsante all'interno con il testo 'Click me'.

Una finestra aperta chiamando Show è una finestra non modale e l'applicazione non impedisce agli utenti di interagire con altre finestre nell'applicazione. L'apertura di una finestra con ShowDialog apre una finestra come modale e limita l'interazione dell'utente alla finestra specifica. Per altre informazioni, vedere Cenni preliminari sulle finestre di dialogo.

Quando viene chiamato il metodo Show, una finestra esegue il processo di inizializzazione prima di essere visualizzata per definire l'infrastruttura che le permette di ricevere l'input dell'utente. Quando la finestra viene inizializzata, viene generato l'evento SourceInitialized e viene visualizzata la finestra.

Per altre informazioni, vedere Come aprire una finestra o una finestra di dialogo.

Finestra di avvio

Nell'esempio precedente è stato usato l'evento Startup per eseguire il codice che ha visualizzato la finestra iniziale dell'applicazione. Per maggiore rapidità, è possibile usare StartupUri per specificare il percorso di un file XAML nell'applicazione. L'applicazione crea e visualizza automaticamente la finestra specificata da tale proprietà.

<Application x:Class="WindowsOverview.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WindowsOverview"
             StartupUri="ClippedWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

Proprietà della finestra

Una finestra aperta tramite il metodo Show non ha una relazione implicita con la finestra che l'ha creata. Gli utenti possono interagire con una finestra indipendentemente dall'altra, il che significa che entrambe le finestre possono:

  • Coprire l'altra (a meno che una delle finestre non abbia la proprietà Topmost impostata su true).
  • Essere ridotte a icona, ingrandite e ripristinate senza influire sull'altra.

Alcune finestre richiedono una relazione con la finestra da cui vengono aperte. Ad esempio, un'applicazione IDE può aprire finestre delle proprietà e finestre degli strumenti, il cui comportamento tipico consiste nel coprire la finestra da cui sono state create. Queste finestre devono inoltre essere chiuse, ridotte a icona, ingrandite e ripristinate insieme alla finestra da cui sono state create. È possibile stabilire una relazione di questo tipo impostando una finestra come proprietaria dell'altra. A questo scopo, impostare la proprietà Owner della finestra di proprietà con un riferimento alla finestra proprietaria, come illustrato nell'esempio seguente.

private void Button_Click(object sender, RoutedEventArgs e)
{
    // Create a window and make the current window its owner
    var ownedWindow = new ChildWindow1();
    ownedWindow.Owner = this;
    ownedWindow.Show();
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    ' Create a window and make the current window its owner
    Dim ownedWindow As New ChildWindow1
    ownedWindow.Owner = Me
    ownedWindow.Show()
End Sub

Dopo aver stabilito la proprietà:

  • La finestra di proprietà può fare riferimento alla finestra proprietaria esaminando il valore della proprietà Owner.
  • La finestra proprietaria può individuare tutte le finestre di sua proprietà esaminando il valore della proprietà OwnedWindows.

Attivazione di finestre

Quando una finestra viene aperta per la prima volta, diventa la finestra attiva. La finestra attiva è la finestra che attualmente acquisisce l'input dell'utente, come le sequenze di tasti e i clic del mouse. Quando una finestra diventa attiva, genera l'evento Activated.

Nota

Quando una finestra viene aperta per la prima volta, gli eventi Loaded e ContentRendered vengono generati solo dopo la generazione dell'evento Activated. Con questa premessa, una finestra può essere effettivamente considerata aperta quando viene generato l'evento ContentRendered.

Dopo l'attivazione di una finestra, un utente può attivare un'altra finestra nella stessa applicazione oppure attivare un'altra applicazione. In questo caso, la finestra attualmente attiva viene disattivata e genera l'evento Deactivated. Analogamente, quando l'utente seleziona una finestra attualmente disattivata, la finestra diventa nuovamente attiva e genera l'evento Activated.

Un motivo comune per gestire Activated e Deactivated consiste nell'abilitare e disabilitare le funzionalità che possono essere eseguite solo quando una finestra è attiva. Ad esempio, alcune finestre mostrano contenuto interattivo che richiede un input utente o un'attenzione costante, tra cui giochi e lettori video. L'esempio seguente è un lettore video semplificato che illustra come gestire Activated e Deactivated per implementare questo comportamento.

<Window x:Class="WindowsOverview.CustomMediaPlayerWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Activated="Window_Activated"
        Deactivated="Window_Deactivated"
        Title="CustomMediaPlayerWindow" Height="450" Width="800">
    <Grid>
        <MediaElement x:Name="mediaElement" Stretch="Fill"
                      LoadedBehavior="Manual" Source="numbers.mp4" />
    </Grid>
</Window>

Il codice seguente è il code-behind per il markup XAML.

using System;
using System.Windows;

namespace WindowsOverview
{
    public partial class CustomMediaPlayerWindow : Window
    {
        public CustomMediaPlayerWindow() =>
            InitializeComponent();

        private void Window_Activated(object sender, EventArgs e)
        {
            // Continue playing media if window is activated
            mediaElement.Play();
        }

        private void Window_Deactivated(object sender, EventArgs e)
        {
            // Pause playing if media is being played and window is deactivated
            mediaElement.Pause();
        }
    }
}
Public Class CustomMediaPlayerWindow
    Private Sub Window_Activated(sender As Object, e As EventArgs)
        ' Continue playing media if window Is activated
        mediaElement.Play()
    End Sub

    Private Sub Window_Deactivated(sender As Object, e As EventArgs)
        ' Pause playing if media is being played and window is deactivated
        mediaElement.Pause()
    End Sub
End Class

Altri tipi di applicazioni possono comunque eseguire codice in background quando una finestra è disattivata. Ad esempio, un client di posta elettronica può continuare a eseguire il polling del server di posta elettronica mentre l'utente usa altre applicazioni. Applicazioni come queste forniscono un comportamento diverso o aggiuntivo mentre la finestra principale è disattivata. Per un programma di posta elettronica, questo significa aggiungere il nuovo elemento di posta elettronica nella posta in arrivo e aggiungere un'icona di notifica sulla barra delle applicazioni. Un'icona di notifica deve essere visualizzata solo quando la finestra di posta elettronica non è attiva, aspetto che può essere determinato esaminando la proprietà IsActive.

Se viene completata un'attività in background, una finestra potrebbe voler informare l'utente più urgentemente chiamando il metodo Activate. Se l'utente sta interagendo con un'altra applicazione attivata quando viene chiamato Activate, il pulsante della finestra sulla barra delle applicazioni lampeggia. Tuttavia, se l'utente sta interagendo con l'applicazione corrente, la chiamata di Activate porta la finestra in primo piano.

Nota

È possibile gestire l'attivazione dell'ambito applicazione usando gli eventi Application.Activated e Application.Deactivated.

Impedire l'attivazione delle finestre

In alcuni scenari le finestre non devono essere attivate quando vengono visualizzate, ad esempio le finestre di conversazione di un'applicazione di chat o le finestre di notifica di un'applicazione di posta elettronica.

Se l'applicazione include una finestra che non deve essere attivata quando viene visualizzata, è possibile impostarne la proprietà ShowActivated su false prima di chiamare il metodo Show per la prima volta. Di conseguenza:

  • La finestra non è attivata.
  • L'evento Activated della finestra non viene generato.
  • La finestra attualmente attivata resta attivata.

La finestra viene attivata, tuttavia, non appena l'utente fa clic sull'area client o non client. In questo caso:

  • La finestra viene attivata.
  • L'evento Activated della finestra viene generato.
  • La finestra precedentemente attivata viene disattivata.
  • Gli eventi Deactivated e Activated della finestra vengono quindi generati come previsto in risposta alle azioni dell'utente.

Chiusura di una finestra

La durata di una finestra si avvicina alla fine quando la finestra viene chiusa da un utente. Una volta chiusa una finestra, non può essere riaperta. Una finestra può essere chiusa tramite elementi nell'area non client, tra cui i seguenti:

  • Voce Chiudi del menu Sistema.
  • ALT + F4.
  • Pulsante Chiudi.
  • Tasto ESC quando un pulsante ha la proprietà IsCancel impostata su true su una finestra modale.

È possibile fornire più meccanismi all'area client per chiudere una finestra, i più comuni dei quali includono:

  • Voce Esci nel menu File, in genere per la finestra principale dell'applicazione.
  • Voce Chiudi nel menu File, in genere in una finestra dell'applicazione secondaria.
  • Pulsante Annulla, in genere in una finestra di dialogo modale.
  • Pulsante Chiudi, in genere in una finestra di dialogo non modale.

Per chiudere una finestra in risposta a uno di questi meccanismi personalizzati, è necessario chiamare il metodo Close. L'esempio seguente implementa la possibilità di chiudere una finestra scegliendo Esci dal menu File.

<Window x:Class="WindowsOverview.ClosingWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ClosingWindow" Height="450" Width="800">
    <StackPanel>
        <Menu>
            <MenuItem Header="_File">
                <MenuItem Header="E_xit" Click="fileExitMenuItem_Click" />
            </MenuItem>
        </Menu>
    </StackPanel>
</Window>

Il codice seguente è il code-behind per il markup XAML.

using System.Windows;

namespace WindowsOverview
{
    public partial class ClosingWindow : Window
    {
        public ClosingWindow() =>
            InitializeComponent();

        private void fileExitMenuItem_Click(object sender, RoutedEventArgs e)
        {
            // Close the current window
            this.Close();
        }
    }
}
Public Class ClosingWindow
    Private Sub fileExitMenuItem_Click(sender As Object, e As RoutedEventArgs)
        ' Close the current window
        Me.Close()
    End Sub
End Class

Nota

Un'applicazione può essere configurata per l'arresto immediato alla chiusura della finestra principale dell'applicazione (vedere MainWindow) o dell'ultima finestra. Per ulteriori informazioni, vedere ShutdownMode.

Mentre una finestra può essere chiusa in modo esplicito tramite meccanismi forniti nelle aree non client e client, una finestra può anche essere chiusa in modo implicito come risultato di comportamenti in altre parti dell'applicazione o di Windows, tra cui:

  • Un utente si disconnette da Windows o arresta il sistema.
  • Un elemento Owner della finestra viene chiuso.
  • La finestra dell'applicazione principale viene chiusa e ShutdownMode è OnMainWindowClose.
  • Viene chiamato Shutdown.

Importante

Una volta chiusa, una finestra non può essere riaperta.

Annullare la chiusura di finestra

Quando una finestra viene chiusa, genera due eventi: Closing e Closed.

Closing viene generato prima della chiusura della finestra e fornisce un meccanismo tramite il quale è possibile impedire la chiusura della finestra. Un motivo comune per cui impedire la chiusura di una finestra è se la finestra contiene dati modificati. In questa situazione, è possibile gestire l'evento Closing per determinare se i dati sono stati modificati ma non salvati e, in questo caso, chiedere all'utente se chiudere comunque la finestra senza salvare i dati o se annullare la chiusura della finestra. Nell'esempio seguente vengono illustrati gli aspetti principali della gestione di Closing.

<Window x:Class="WindowsOverview.DataWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataWindow" Height="450" Width="800"
        Closing="Window_Closing">
    <Grid>
        <TextBox x:Name="documentTextBox" TextChanged="documentTextBox_TextChanged" />
    </Grid>
</Window>

Il codice seguente è il code-behind per il markup XAML.

using System.Windows;
using System.Windows.Controls;

namespace WindowsOverview
{
    public partial class DataWindow : Window
    {
        private bool _isDataDirty;

        public DataWindow() =>
            InitializeComponent();

        private void documentTextBox_TextChanged(object sender, TextChangedEventArgs e) =>
            _isDataDirty = true;

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // If data is dirty, prompt user and ask for a response
            if (_isDataDirty)
            {
                var result = MessageBox.Show("Document has changed. Close without saving?",
                                             "Question",
                                             MessageBoxButton.YesNo);

                // User doesn't want to close, cancel closure
                if (result == MessageBoxResult.No)
                    e.Cancel = true;
            }
        }
    }
}
Public Class DataWindow

    Private _isDataDirty As Boolean

    Private Sub documentTextBox_TextChanged(sender As Object, e As TextChangedEventArgs)
        _isDataDirty = True
    End Sub

    Private Sub Window_Closing(sender As Object, e As ComponentModel.CancelEventArgs)

        ' If data is dirty, prompt user and ask for a response
        If _isDataDirty Then
            Dim result = MessageBox.Show("Document has changed. Close without saving?",
                                         "Question",
                                         MessageBoxButton.YesNo)

            ' User doesn't want to close, cancel closure
            If result = MessageBoxResult.No Then
                e.Cancel = True
            End If
        End If

    End Sub
End Class

Al gestore eventi Closing viene passato CancelEventArgs, che implementa la proprietà Cancel impostata su true per impedire la chiusura di una finestra.

Se Closing non viene gestito o viene gestito ma non annullato, la finestra verrà chiusa. Poco prima della chiusura di una finestra, viene generato l'evento Closed. A questo punto, non è più possibile impedire la chiusura di una finestra.

Eventi di durata di una finestra

La figura seguente mostra la sequenza degli eventi principali per la durata di una finestra:

Diagramma che mostra gli eventi per la durata di una finestra.

La figura seguente mostra la sequenza dei principali eventi per la durata di una finestra visualizzata senza attivazione (false è impostato su ShowActivated prima della visualizzazione della finestra):

Diagramma che mostra gli eventi per la durata di una finestra senza attivazione.

Posizione della finestra

Mentre è aperta, una finestra ha una posizione nelle dimensioni x e y relative al desktop. Questa posizione può essere determinata esaminando rispettivamente le proprietà Left e Top. Impostare queste proprietà per modificare la posizione della finestra.

È anche possibile specificare la posizione iniziale di una Window quando viene visualizzata per la prima volta impostando la proprietà WindowStartupLocation con uno dei valori di enumerazione WindowStartupLocation seguenti:

Se la posizione iniziale viene specificata come Manual e le proprietà Left e Top non sono state impostate, Window chiederà al sistema operativo di visualizzare una posizione.

Finestre in primo piano e ordine z

Oltre ad avere una posizione nelle dimensioni x e y, una finestra ha anche una dimensione z, che ne determina la posizione verticale rispetto alle altre finestre. Questo concetto è noto con il nome di ordine z della finestra e ne esistono due tipi: ordine z normale e ordine z in primo piano. La posizione di una finestra in base all'ordine z normale è determinata dal fatto che la finestra sia o meno attualmente attiva. Per impostazione predefinita, una finestra è posizionata in base all'ordine z normale. Anche la posizione di una finestra in base all'ordine z in primo piano è determinata dal fatto che la finestra sia o meno attualmente attiva. Inoltre, le finestre posizionate in base all'ordine z in primo piano si trovano sempre al di sopra di quelle posizionate in base all'ordine z normale. Per posizionare una finestra in base all'ordine z in primo piano, impostarne la proprietà Topmost su true.

In entrambi gli ordini z la finestra attualmente attiva viene visualizzata al di sopra delle altre finestre in base allo stesso ordine z.

Dimensioni finestra

Oltre a una posizione sul desktop, una finestra ha anche dimensioni determinate da diverse proprietà, tra cui le diverse proprietà di larghezza e altezza e SizeToContent.

MinWidth, Width e MaxWidth vengono usate per gestire l'intervallo di larghezze che una finestra può avere per la sua durata.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    MinWidth="300" Width="400" MaxWidth="500">
</Window>

L'altezza della finestra è gestita da MinHeight, Height e MaxHeight.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    MinHeight="300" Height="400" MaxHeight="500">
</Window>

Poiché i diversi valori di larghezza e di altezza specificano ognuno un intervallo, la larghezza e l'altezza di una finestra ridimensionabile possono corrispondere a qualsiasi valore all'interno dell'intervallo specificato per la rispettiva dimensione. Per rilevare la larghezza e l'altezza correnti, esaminare rispettivamente ActualWidth e ActualHeight.

Se si vuole che la larghezza e l'altezza della finestra abbiano dimensioni corrispondenti alle dimensioni del contenuto della finestra, è possibile usare la proprietà SizeToContent, che ha i valori seguenti:

L'esempio seguente mostra una finestra che si ridimensiona automaticamente in base al contenuto, sia in verticale sia in orizzontale, quando viene visualizzata per la prima volta.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    SizeToContent="WidthAndHeight">
</Window>

L'esempio seguente mostra come impostare la proprietà SizeToContent nel codice per specificare il modo in cui una finestra si ridimensiona per adattarsi al contenuto.

// Manually alter window height and width
this.SizeToContent = SizeToContent.Manual;

// Automatically resize width relative to content
this.SizeToContent = SizeToContent.Width;

// Automatically resize height relative to content
this.SizeToContent = SizeToContent.Height;

// Automatically resize height and width relative to content
this.SizeToContent = SizeToContent.WidthAndHeight;
' Manually alter window height and width
Me.SizeToContent = SizeToContent.Manual

' Automatically resize width relative to content
Me.SizeToContent = SizeToContent.Width

' Automatically resize height relative to content
Me.SizeToContent = SizeToContent.Height

' Automatically resize height and width relative to content
Me.SizeToContent = SizeToContent.WidthAndHeight

Ordine di precedenza per le proprietà di dimensionamento

Essenzialmente, le diverse proprietà per le dimensioni di una finestra si combinano per definire gli intervalli di larghezza e altezza per una finestra ridimensionabile. Per garantire che venga mantenuto un intervallo valido, Window valuta i valori delle proprietà di dimensione usando gli ordini di precedenza seguenti.

Per le proprietà di altezza:

  1. FrameworkElement.MinHeight
  2. FrameworkElement.MaxHeight
  3. SizeToContent.Height / SizeToContent.WidthAndHeight
  4. FrameworkElement.Height

Per le proprietà di larghezza:

  1. FrameworkElement.MinWidth
  2. FrameworkElement.MaxWidth
  3. SizeToContent.Width / SizeToContent.WidthAndHeight
  4. FrameworkElement.Width

L'ordine di precedenza può anche determinare le dimensioni di una finestra quando è ingrandita, operazione gestita con la proprietà WindowState.

Window state

Per la sua durata, una finestra ridimensionabile può avere tre stati: normale, ridotta a icona e ingrandita. Lo stato normale è lo stato predefinito di una finestra. Una finestra con questo stato permette a un utente di spostarla e ridimensionarla usando un controllo di ridimensionamento o il bordo, se è ridimensionabile.

Una finestra ridotta a icona viene compressa al pulsante corrispondente sulla barra delle applicazioni se la proprietà ShowInTaskbar è impostata su true; in caso contrario, viene compressa in base alle dimensioni minori possibile e riposizionata nell'angolo inferiore sinistro del desktop. Nessuno dei due tipi di finestra ridotta a icona può essere ridimensionato tramite un bordo o un controllo di ridimensionamento, anche se una finestra ridotta a icona non visualizzata sulla barra delle applicazioni può essere trascinata sul desktop.

Una finestra con uno stato ingrandito si espande fino alle dimensioni massime previste, determinate dalle proprietà MaxWidth, MaxHeight e SizeToContent. Come per una finestra ridotta a icona, una finestra ingrandita non può essere ridimensionata tramite un controllo di ridimensionamento o trascinandone il bordo.

Nota

I valori delle proprietà Top, Left, Width e Height di una finestra rappresentano sempre i valori per lo stato normale, anche quando la finestra è attualmente ingrandita o ridotta a icona.

Lo stato di una finestra può essere configurato impostando la relativa proprietà WindowState, che può avere uno dei valori di enumerazione WindowState seguenti:

L'esempio seguente mostra come creare una finestra visualizzata come ingrandita quando viene aperta.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowState="Maximized">
</Window>

In generale, è consigliabile impostare WindowState per configurare lo stato iniziale di una finestra. Una volta visualizzata una finestra ridimensionabile, gli utenti possono premere i pulsanti Riduci a icona, Ingrandisci e Ripristina sulla barra del titolo della finestra per modificarne lo stato.

Aspetto della finestra

Per modificare l'aspetto dell'area client di una finestra, è necessario aggiungervi contenuto specifico della finestra, come pulsanti, etichette e caselle di testo. Per configurare l'area non client, Window fornisce diverse proprietà, tra cui Icon per impostare l'icona di una finestra e Title per impostarne il titolo.

È anche possibile modificare l'aspetto e il comportamento del bordo dell'area non client configurando la modalità di ridimensionamento di una finestra, lo stile della finestra e se la finestra verrà o meno visualizzata come pulsante sulla barra delle applicazioni del desktop.

Modalità di ridimensionamento

A seconda della proprietà WindowStyle, è possibile controllare se e come ridimensionare la finestra. Lo stile della finestra influisce sugli elementi seguenti:

  • Consente o non consente il ridimensionamento trascinando il bordo della finestra con il mouse.
  • Se i pulsanti Riduci a icona, Ingrandisci e Chiudi vengono visualizzati nell'area non client.
  • Se i pulsanti Riduci a icona, Ingrandisci e Chiudi sono abilitati.

È possibile configurare la modalità di ridimensionamento di una finestra impostando la relativa proprietà ResizeMode, che può avere uno dei valori di enumerazione ResizeMode seguenti:

Come con WindowStyle, è improbabile che la modalità di ridimensionamento di una finestra cambi per la sua durata e questo significa che presumibilmente questa impostazione è stata configurata dal markup XAML.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ResizeMode="CanResizeWithGrip">
</Window>

È possibile identificare se una finestra è ingrandita, ridotta a icona o ripristinata esaminando la proprietà WindowState.

Window style

Il bordo esposto dall'area non client di una finestra è adatto per la maggior parte delle applicazioni. In alcuni casi, tuttavia, sono necessari tipi di bordi diversi oppure non è necessario alcun bordo, a seconda del tipo di finestra.

Per controllare il tipo di bordo ottenuto da una finestra, impostare la relativa proprietà WindowStyle con uno dei valori seguenti dell'enumerazione WindowStyle:

L'effetto dell'applicazione di uno stile di finestra è illustrato nell'immagine seguente:

Screenshot che mostra come lo stile di finestra influisce su una finestra in WPF.

Si noti che l'immagine precedente non mostra alcuna differenza evidente tra SingleBorderWindow e ThreeDBorderWindow. In Windows XP, ThreeDBorderWindow influiva sul modo in cui era disegnata la finestra, aggiungendo un bordo 3D all'area client. A partire da Windows 7, le differenze tra i due stili sono minime.

È possibile impostare WindowStyle usando il markup XAML o il codice. Poiché è improbabile che venga modificato nel corso della durata di una finestra, quasi certamente si deciderà di configurare lo stile usando il markup XAML.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowStyle="ToolWindow">
</Window>

Stile di finestra non rettangolare

In alcuni casi, gli stili di bordo consentiti da WindowStyle non sono sufficienti. Ad esempio, si potrebbe voler creare un'applicazione con un bordo non rettangolare, come quelli usati da Microsoft Windows Media Player.

Ad esempio, si consideri la finestra a fumetto mostrata nella figura seguente:

Screenshot di una finestra di WPF con un'area ritagliata e una forma personalizzata.

Questo tipo di finestra può essere creato impostando la proprietà WindowStyle su Nonee usando un supporto speciale di Window per la trasparenza.

<Window x:Class="WindowsOverview.ClippedWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ClippedWindow" SizeToContent="WidthAndHeight"
        WindowStyle="None" AllowsTransparency="True" Background="Transparent">
    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="20"/>
        </Grid.RowDefinitions>

        <Rectangle Stroke="#FF000000" RadiusX="10" RadiusY="10"/>
        <Path Fill="White" Stretch="Fill" Stroke="#FF000000" HorizontalAlignment="Left" Margin="15,-5.597,0,-0.003" Width="30" Grid.Row="1" Data="M22.166642,154.45381 L29.999666,187.66699 40.791059,154.54395"/>
        <Rectangle Fill="White" RadiusX="10" RadiusY="10" Margin="1"/>
        
        <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="25" Text="Greetings!" TextWrapping="Wrap" Margin="5,5,50,5"/>
        <Button HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" BorderBrush="{x:Null}" Foreground="Red" Content="❌" FontSize="15" />

        <Grid.Effect>
            <DropShadowEffect BlurRadius="10" ShadowDepth="3" Color="LightBlue"/>
        </Grid.Effect>
    </Grid>
</Window>

Questa combinazione di valori specifica che la finestra deve essere visualizzata come trasparente. In questo stato, i pulsanti di adornamento dell'area non client della finestra non possono essere usati ed è necessario specificare i propri.

Presenza sulla barra delle applicazioni

L'aspetto predefinito di una finestra include un pulsante della barra delle applicazioni. Alcuni tipi di finestre non dispongono di un pulsante della barra delle applicazioni, ad esempio finestre di messaggio, finestre di dialogo o finestre con la proprietà WindowStyle impostata su ToolWindow. È possibile controllare se il pulsante della barra delle applicazioni per una finestra è visualizzato o meno impostando la proprietà ShowInTaskbar (true per impostazione predefinita).

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ShowInTaskbar="False">
</Window>

Altri tipi di finestre

NavigationWindow è una finestra progettata per ospitare contenuto navigabile.

Le finestre di dialogo sono finestre usate spesso per raccogliere informazioni da un utente in modo da completare una funzione. Ad esempio, quando un utente vuole aprire un file, un'applicazione visualizza in genere la finestra di dialogo Apri file per ottenere il nome del file dall'utente. Per altre informazioni, vedere Cenni preliminari sulle finestre di dialogo.

Vedi anche