Ambiti dei nomi XAML WPF

Un ambito dei nomi XAML è un concetto che identifica gli oggetti definiti in XAML. I nomi in un ambito dei nomi XAML possono essere usati per stabilire relazioni tra i nomi definiti da XAML degli oggetti e i rispettivi equivalenti di istanza in un albero di oggetti. In genere, gli ambiti dei nomi XAML nel codice gestito WPF vengono creati durante il caricamento delle singole radici di pagina XAML per un'applicazione XAML. Gli ambiti dei nomi XAML come oggetto di programmazione sono definiti dall'interfaccia INameScope e vengono implementati anche dalla classe NameScopepratica .

Ambiti dei nomi in applicazioni XAML caricate

In un più ampio contesto di programmazione o informatico i concetti di programmazione includono spesso il principio di identificatore o nome univoco, che può essere usato per accedere a un oggetto. Per i sistemi che usano identificatori o nomi, l'ambito dei nomi definisce i limiti entro i quali un processo o una tecnica individuerà se è necessario un oggetto con tale nome oppure i limiti entro i quali viene applicata l'univocità dei nomi di identificazione. Questi principi generali si applicano agli ambiti dei nomi XAML. In WPF gli ambiti dei nomi XAML vengono creati nell'elemento radice per una pagina XAML quando questa viene caricata. Ogni nome specificato nella pagina XAML che inizia in corrispondenza della radice della pagina viene aggiunto a un ambito dei nomi XAML pertinente.

In XAML WPF, gli elementi che sono elementi radice comuni (ad esempio Page, e Window) controllano sempre un ambito dei nomi XAML. Se un elemento come FrameworkElement o FrameworkContentElement è l'elemento radice della pagina nel markup, un processore XAML aggiunge una Page radice in modo implicito in modo che Page possa fornire un ambito dei nomi XAML funzionante.

Nota

Le azioni di compilazione WPF creano un ambito dei nomi XAML per una produzione XAML anche se non Name sono definiti attributi o x:Name su qualsiasi elemento del markup XAML.

Se si prova a usare lo stesso nome due volte in un ambito dei nomi XAML, viene generata un'eccezione. Per codice XAML WPF che include code-behind e che fa parte di un'applicazione compilata, l'eccezione viene generata in fase di compilazione dalle azioni di compilazione di WPF, quando viene creata la classe generata per la pagina durante la compilazione iniziale del markup. Per codice XAML non compilato dal markup tramite alcuna azione di compilazione, potrebbero essere generate eccezioni correlate a problemi dell'ambito dei nomi XAML durante il caricamento di XAML. I progettisti XAML possono anche prevedere i problemi relativi all'ambito dei nomi XAML in fase di progettazione.

Aggiunta di oggetti all'albero di oggetti di runtime

Il momento in cui XAML viene analizzato rappresenta il momento in cui viene creato e definito un ambito dei nomi XAML WPF. Se si aggiunge un oggetto a un albero di oggetti in un momento successivo all'analisi del codice XAML che ha prodotto l'albero, un valore Name o x:Name nel nuovo oggetto non aggiorna automaticamente le informazioni in un ambito dei nomi XAML. Per aggiungere un nome per un oggetto in un ambito dei nomi XAML WPF dopo il caricamento di XAML, devi chiamare l'implementazione appropriata di nell'oggetto che definisce l'ambito dei nomi XAML, che in genere è la radice della RegisterName pagina XAML. Se il nome non è registrato, l'oggetto aggiunto non può essere fatto riferimento in base al nome tramite metodi come FindNamee non è possibile usare tale nome per la destinazione dell'animazione.

Lo scenario più comune per gli sviluppatori di applicazioni consiste nell'usare RegisterName per registrare i nomi nell'ambito dei nomi XAML nella radice corrente della pagina. RegisterName fa parte di uno scenario importante per gli storyboard destinati agli oggetti per le animazioni. Per altre informazioni, vedere Cenni preliminari sugli storyboard.

Se chiami RegisterName su un oggetto diverso dall'oggetto che definisce l'ambito dei nomi XAML, il nome è ancora registrato nell'ambito dei nomi XAML in cui si trova l'oggetto chiamante, come se avessi chiamato RegisterName nell'ambito dei nomi XAML che definisce l'oggetto.

Ambiti dei nomi XAML nel codice

È possibile creare e quindi usare ambiti dei nomi XAML nel codice. Le API e i concetti coinvolti nella creazione dell'ambito dei nomi XAML sono gli stessi anche per un utilizzo di codice puro, perché il processore XAML per WPF usa queste API e concetti quando elabora xaml stesso. I concetti e le API hanno prevalentemente lo scopo di trovare oggetti in base al nome all'interno di un albero di oggetti definito parzialmente o interamente in XAML.

Per le applicazioni create a livello di codice e non da XAML caricato, l'oggetto che definisce un ambito dei nomi XAML deve implementare INameScopeo essere una FrameworkElement classe derivata o FrameworkContentElement per supportare la creazione di un ambito dei nomi XAML nelle relative istanze.

Inoltre, per qualsiasi elemento che non viene caricato ed elaborato da un processore XAML, l'ambito dei nomi XAML per l'oggetto non viene creato o inizializzato per impostazione predefinita. È necessario creare un nuovo ambito dei nomi XAML per qualsiasi oggetto in cui si intende successivamente registrare nomi. Per creare un ambito dei nomi XAML, chiamare il metodo statico SetNameScope . Specificare l'oggetto proprietario come dependencyObject parametro e una nuova NameScope chiamata al value costruttore come parametro.

Se l'oggetto fornito come dependencyObject per SetNameScope non è un'implementazione INameScopeFrameworkElement o FrameworkContentElement, la chiamata RegisterName a qualsiasi elemento figlio non avrà alcun effetto. Se non si crea il nuovo ambito dei nomi XAML in modo esplicito, le chiamate a RegisterName genereranno un'eccezione.

Per un esempio dell'uso di API di ambito dei nomi XAML nel codice, vedere Definire un ambito dei nomi.

Ambiti dei nomi XAML in stili e modelli

Gli stili e i modelli in WPF consentono di riutilizzare e riapplicare il contenuto in modo semplice. Tuttavia, stili e modelli potrebbero includere anche elementi con nomi XAML definiti a livello del modello. Questo stesso modello potrebbe essere usato più volte in una pagina. Per questo motivo, gli stili e i modelli definiscono entrambi ambiti dei nomi XAML propri, indipendentemente dalla posizione in un albero di oggetti in cui viene applicato lo stile o il modello.

Si consideri l'esempio seguente:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <Page.Resources>
    <ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
      <Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
        <ContentPresenter/>
      </Border>      
    </ControlTemplate>
  </Page.Resources>
  <StackPanel>
    <Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
    <Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
  </StackPanel>
</Page>

Qui viene applicato lo stesso modello a due diversi pulsanti. Se i modelli non avessero ambiti dei nomi XAML discreti, il nome TheBorder usato nel modello causerebbe un conflitto di nomi nell'ambito dei nomi XAML. Poiché la creazione di ogni istanza del modello ha un ambito dei nomi XAML proprio, in questo esempio l'ambito dei nomi di ogni modello di cui è stata creata un'istanza contiene esattamente un solo nome.

Anche gli stili definiscono un ambito dei nomi XAML proprio, per lo più in modo che alle parti degli storyboard possano essere assegnati nomi specifici. Questi nomi permettono comportamenti specifici dei controlli destinati a elementi con questi nomi, anche se il modello è stato ridefinito come parte della personalizzazione del controllo.

A causa della presenza di ambiti dei nomi XAML separati, la ricerca di elementi denominati in un modello è più complessa rispetto all'individuazione di un elemento denominato senza modello in una pagina. Per prima cosa è necessario determinare il modello applicato, ottenendo il Template valore della proprietà del controllo in cui viene applicato il modello. Chiamare quindi la versione del modello di FindName, passando il controllo in cui è stato applicato il modello come secondo parametro.

Se si è un autore di controlli e si sta generando una convenzione in cui un particolare elemento denominato in un modello applicato è la destinazione per un comportamento definito dal controllo stesso, è possibile usare il GetTemplateChild metodo dal codice di implementazione del controllo. Il GetTemplateChild metodo è protetto, quindi solo l'autore del controllo può accedervi.

Se si lavora dall'interno di un modello ed è necessario accedere all'ambito dei nomi XAML in cui viene applicato il modello, ottenere il valore di TemplatedParente quindi chiamarlo FindName . Un esempio di questa situazione è quando si scrive l'implementazione del gestore eventi in cui l'evento verrà generato da un elemento in un modello applicato.

FrameworkElement dispone di FindNamemetodi , RegisterName e UnregisterName . Se l'oggetto in cui vengono chiamati questi metodi è proprietario di un ambito dei nomi XAML, i metodi chiamano nei metodi dell'ambito dei nomi XAML pertinente. In caso contrario, l'elemento padre viene controllato per verificare se è proprietario di un ambito dei nomi XAML e questo processo continua in modo ricorsivo fino a quando non viene trovato un ambito dei nomi XAML. A causa del comportamento del processore XAML, esiste sicuramente un ambito dei nomi XAML nella radice. FrameworkContentElement ha comportamenti analoghi, con l'eccezione che nessun FrameworkContentElement ambito dei nomi XAML sarà mai proprietario. I metodi esistono in FrameworkContentElement modo che le chiamate possano essere inoltrate a un FrameworkElement elemento padre.

SetNameScope viene usato per eseguire il mapping di un nuovo ambito dei nomi XAML a un oggetto esistente. Puoi chiamare SetNameScope più volte per reimpostare o cancellare l'ambito dei nomi XAML, ma non è un utilizzo comune. Inoltre, GetNameScope non viene in genere usato dal codice.

Implementazioni di ambiti dei nomi XAML

Le classi seguenti implementano INameScope direttamente:

ResourceDictionary non usa nomi XAML o ambiti dei nomi ; usa invece le chiavi, perché è un'implementazione del dizionario. L'unico motivo per ResourceDictionary cui implementa INameScope è che può generare eccezioni al codice utente che consentono di chiarire la distinzione tra un vero ambito dei nomi XAML e come ResourceDictionary gestisce le chiavi e anche per garantire che gli ambiti dei nomi XAML non vengano applicati a un ResourceDictionary oggetto dagli elementi padre.

FrameworkTemplate e Style implementare INameScope tramite definizioni di interfaccia esplicite. Le implementazioni esplicite consentono a questi ambiti dei nomi XAML di comportarsi in modo convenzionale quando si accede tramite l'interfaccia INameScope , ovvero il modo in cui gli ambiti dei nomi XAML vengono comunicati dai processi interni WPF. Tuttavia, le definizioni di interfaccia esplicite non fanno parte della superficie DELL'API convenzionale di FrameworkTemplate e Style, perché raramente è necessario chiamare i INameScope metodi su FrameworkTemplate e Style direttamente e usare invece altre API, ad GetTemplateChildesempio .

Le classi seguenti definiscono il proprio ambito dei nomi XAML, usando la System.Windows.NameScope classe helper e connettendosi all'implementazione dell'ambito dei nomi XAML tramite la NameScope.NameScope proprietà associata:

Vedi anche