Zakresy nazw WPF XAML

Zakresy nazw XAML to pojęcie identyfikujące obiekty zdefiniowane w języku XAML. Nazwy w zakresach nazw XAML mogą służyć do ustanawiania relacji między nazwami obiektów zdefiniowanymi w języku XAML i ich odpowiednikami wystąpienia w drzewie obiektów. Zazwyczaj zakresy nazw XAML w kodzie zarządzanym WPF są tworzone podczas ładowania poszczególnych katalogów głównych stron XAML dla aplikacji XAML. Zakresy nazw XAML jako obiekt programowania są definiowane przez INameScope interfejs i są również implementowane przez praktyczną klasę NameScope.

Zakresy nazw w załadowanych aplikacjach XAML

W szerszym kontekście programowania lub informatyki pojęcia programistyczne często obejmują zasadę unikatowego identyfikatora lub nazwy, która może służyć do uzyskiwania dostępu do obiektu. W przypadku systemów, które używają identyfikatorów lub nazw, zakres nazw definiuje granice, w których proces lub technika będzie wyszukiwać, jeśli żądany jest obiekt o tej nazwie, lub granice, w których wymuszana jest unikatowość nazw identyfikujących. Te ogólne zasady są prawdziwe w przypadku zakresów nazw XAML. W WPF zakresy nazw XAML są tworzone w elemencie głównym dla strony XAML podczas ładowania strony. Każda nazwa określona na stronie XAML rozpoczynająca się od katalogu głównego strony jest dodawana do istotnego zakresów nazw XAML.

W języku XAML WPF elementy, które są wspólnymi elementami głównymi ( Pagetakimi jak , i Window), zawsze kontrolują zakres nazw XAML. Jeśli element, taki FrameworkElement jak lub FrameworkContentElement , jest elementem głównym strony w znacznikach, procesor XAML PagePage dodaje katalog główny niejawnie, dzięki czemu element może podać roboczy zakres nazw XAML.

Uwaga

Akcje kompilacji WPF tworzą zakres nazw XAML dla produkcji XAML, Namex:Name nawet jeśli żadne atrybuty lub nie są zdefiniowane dla żadnych elementów w znacznikach XAML.

Jeśli spróbujesz użyć tej samej nazwy dwa razy w dowolnym zakres nazw XAML, jest wywoływany wyjątek. W przypadku języka XAML WPF, który ma kod i jest częścią skompilowanej aplikacji, wyjątek jest wywoływany w czasie kompilacji przez akcje kompilacji WPF podczas tworzenia wygenerowanej klasy dla strony podczas początkowej kompilacji znaczników. W przypadku kodu XAML, który nie jest kompilowany za pomocą żadnych akcji kompilacji, wyjątki związane z problemami z zakresem nazw XAML mogą być wywoływane podczas ładowania kodu XAML. Projektanci XAML mogą również przewidywać problemy z zakresem nazw XAML w czasie projektowania.

Dodawanie obiektów do drzew obiektów środowiska uruchomieniowego

Moment analizowania kodu XAML reprezentuje moment w czasie, w którym jest tworzony i definiowany zakres nazw WPF XAML. Jeśli dodasz obiekt do drzewa obiektów w punkcie w czasie po przesłonieniu tego drzewa w języku XAML, Namex:Name wartość lub nowego obiektu nie zaktualizuje automatycznie informacji w zakresach nazw XAML. Aby dodać nazwę obiektu do zakresów nazw WPF XAML po załadowaniu kodu XAML, RegisterName należy wywołać odpowiednią implementację obiektu w obiekcie definiującym zakres nazw XAML, który jest zazwyczaj katalogiem głównym strony XAML. Jeśli nazwa nie jest zarejestrowana, FindNamedodany obiekt nie może być przywoływał nazwy za pomocą metod takich jak , i nie można użyć tej nazwy do określania wartości docelowej animacji.

Najbardziej powszechnym scenariuszem dla RegisterName deweloperów aplikacji jest użycie funkcji do rejestrowania nazw w zakresach nazw XAML w bieżącym katalogu głównym strony. RegisterName jest częścią ważnego scenariusza dla scenariuszy, które są obiektami docelowymi animacji. Aby uzyskać więcej informacji, zobacz Storyboards Overview (Omówienie storyboards).

RegisterName Jeśli zostanie wywołany obiekt inny niż obiekt definiujący zakres nazw XAML, nazwa jest nadal rejestrowana w zakresie nazw XAML, w ramach który jest przechowywane obiekt wywołujący, RegisterName tak jak w przypadku wywołania obiektu definiującego zakres nazw XAML.

Zakresy nazw XAML w kodzie

W kodzie można tworzyć zakresy nazw XAML, a następnie ich używać. Interfejsy API i pojęcia związane z tworzeniem zakresów nazw XAML są takie same nawet w przypadku czystego użycia kodu, ponieważ procesor XAML dla WPF używa tych interfejsów API i pojęć podczas przetwarzania samego kodu XAML. Pojęcia i interfejs API istnieją głównie w celu znalezienia obiektów według nazwy w drzewie obiektów, które jest zwykle zdefiniowane częściowo lub całkowicie w języku XAML.

W przypadku aplikacji, które są tworzone programowo, a nie z załadowanego kodu XAML, obiekt definiujący zakres nazw XAML musi implementować , lub być klasą pochodną , aby umożliwić tworzenie zakresów nazw XAML INameScopeFrameworkElementFrameworkContentElement w jego wystąpieniach.

Ponadto dla każdego elementu, który nie jest ładowany i przetwarzany przez procesor XAML, zakres nazw XAML dla obiektu nie jest domyślnie tworzony ani zainicjowany. Należy jawnie utworzyć nowy zakres nazw XAML dla każdego obiektu, w przypadku których zamierzasz zarejestrować nazwy w kolejnych wersjach. Aby utworzyć zakres nazw XAML, należy wywołać metodę statyczną SetNameScope . Określ obiekt, który będzie jego właścicielem jako parametr dependencyObject , oraz nowe wywołanie NameScope konstruktora jako value parametr.

Jeśli obiekt podany jako dla dependencyObject nie SetNameScope jest implementacją INameScope , FrameworkElementFrameworkContentElementlub , wywoływanie RegisterName na żadnych elementach podrzędnych nie będzie miało żadnego efektu. Jeśli jawnie nie uda się utworzyć nowego zakresów nazw XAML, wywołania elementu będą RegisterName zgłaszać wyjątek.

Aby uzyskać przykład użycia interfejsów API zakresu nazw XAML w kodzie, zobacz Define a Name Scope (Definiowanie zakresu nazw).

Zakresy nazw XAML w stylach i szablonach

Style i szablony w WPF zapewniają możliwość ponownego użycia i ponownego użycia zawartości w prosty sposób. Jednak style i szablony mogą również zawierać elementy z nazwami XAML zdefiniowanymi na poziomie szablonu. Ten sam szablon może być używany wiele razy na stronie. Z tego powodu style i szablony definiują własne zakresy nazw XAML, niezależnie od lokalizacji w drzewie obiektów, w którym zastosowano styl lub szablon.

Rozpatrzmy następujący przykład:

<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>

W tym miejscu ten sam szablon jest stosowany do dwóch różnych przycisków. Jeśli szablony nie miały dyskretnych zakresów nazw XAML, TheBorder nazwa używana w szablonie spowodowałaby kolizję nazw w zakresach nazw XAML. Każde wystąpienia szablonu mają własny zakres nazw XAML, dlatego w tym przykładzie zakres nazw XAML każdego wystąpienia szablonu będzie zawierać dokładnie jedną nazwę.

Style definiują również własny zakres nazw XAML, przede wszystkim tak, aby części storyboards mogą mieć przypisane konkretne nazwy. Te nazwy umożliwiają sterowanie określonymi zachowaniami, które będą elementami docelowymi tej nazwy, nawet jeśli szablon został ponownie zdefiniowany w ramach dostosowywania kontrolek.

Ze względu na oddzielne zakresy nazw XAML znajdowanie nazwanych elementów w szablonie jest trudniejsze niż znalezienie elementu nazwanego bez szablonu na stronie. Najpierw należy określić zastosowany szablon, korzystając z Template wartości właściwości kontrolki, w której szablon jest stosowany. Następnie należy wywołać wersję szablonu FindNameprogramu , przekazując kontrolkę, w której zastosowano szablon jako drugi parametr.

Jeśli jesteś autorem kontrolki i generujesz konwencję, w której określony nazwany element w zastosowanym szablonie jest elementem docelowym zachowania zdefiniowanego przez samą kontrolkę, GetTemplateChild możesz użyć metody z kodu implementacji kontrolki. Metoda GetTemplateChild jest chroniona, więc tylko autor kontrolki ma do niego dostęp.

Jeśli pracujesz z poziomu szablonu i chcesz uzyskać dostęp do zakresów nazw XAML, w których zastosowano szablon, TemplatedParentpobierz wartość , a następnie wywołaj w FindName tym miejscu. Przykładem pracy w ramach szablonu może być napisanie implementacji procedury obsługi zdarzeń, w której zdarzenie zostanie podniesione z elementu w zastosowanym szablonie.

FrameworkElementMa FindNamemetody , UnregisterNameRegisterName i . Jeśli obiekt, który należy do tych metod, jest właścicielem zakresów nazw XAML, metody wywołują metody odpowiedniego zakresów nazw XAML. W przeciwnym razie element nadrzędny jest sprawdzany w celu sprawdzenia, czy jest właścicielem zakresów nazw XAML, a ten proces jest kontynuowany cyklicznie do momentu, gdy zostanie znaleziony zakres nazw XAML (ze względu na zachowanie procesora XAML gwarantuje się, że w katalogu głównym będzie się pojawiał zakres nazw XAML). FrameworkContentElement Ma analogiczne zachowania, z wyjątkiem tego, że żaden FrameworkContentElement nie będzie kiedykolwiek właścicielem zakresów nazw XAML. Metody istnieją w elemencie FrameworkContentElement , dzięki czemu wywołania mogą być ostatecznie przekazywane do elementu FrameworkElement nadrzędnego.

SetNameScope Służy do mapowania nowego zakres nazw XAML do istniejącego obiektu. Można wywołać więcej niż SetNameScope raz, aby zresetować lub wyczyścić zakres nazw XAML, ale nie jest to typowe użycie. Ponadto typowo GetNameScope nie jest używany z kodu.

Implementacje zakresów nazw XAML

Następujące klasy implementują bezpośrednio INameScope :

ResourceDictionary nie używa nazw XAML ani zakresów nazw ; Zamiast tego używa kluczy, ponieważ jest to implementacja słownika. ResourceDictionaryINameScope Jedyną przyczyną implementacji jest to, że może ona zgłaszać wyjątki w kodzie użytkownika, które pomagają wyjaśnić rozróżnienie między prawdziwym zakresem nazw XAML a sposobem obsługi kluczy, a ResourceDictionary także zapewnić, że zakresy nazw XAML ResourceDictionary nie będą stosowane do elementu przez elementy nadrzędne.

FrameworkTemplate i Style implementować za INameScope pomocą jawnych definicji interfejsu. Jawne implementacje umożliwiają konwencjonalnym zachowaniem tych zakresów nazw XAML INameScope , gdy są one dostępne za pośrednictwem interfejsu, czyli sposobu, w jaki zakresy nazw XAML są komunikowane przez wewnętrzne procesy WPF. Jednak jawne definicje interfejsu nie są częścią konwencjonalnej powierzchni interfejsu API i , FrameworkTemplateINameScopeStyle ponieważ rzadko trzeba wywołać metody bezpośrednio i na i , a zamiast tego użyć innych interfejsów API FrameworkTemplateStyle, takich jak .GetTemplateChild

Następujące klasy definiują własny zakres nazw XAML, System.Windows.NameScope używając klasy pomocnika i łącząc się z jej implementacją zakresów nazw XAML za pośrednictwem dołączonej NameScope.NameScope właściwości:

Zobacz też