http://schemas.microsoft.com/winfx/2006/xaml/presentation definition
When you create a new WpfApplication project in Visual Studio you get the following XAML. Copying and pasting the URL http://schemas.microsoft.com/winfx/2006/xaml/presentation into the browser I expected to see the XSD file definition but I get an error. Why? Thanks.
asked Aug 26, 2014 at 14:46
8,534 19 19 gold badges 70 70 silver badges 134 134 bronze badges
Keep in mind that XML Namespaces are defined by a URL, but that URL doesn’t necessarily have to point to the actual XSD (or anything for that matter). As long as the string it unique and the same string is used by all parties involved with the XML, it is fine.
Aug 26, 2014 at 15:25
@Frank: Does it mean that I can use schemas.today.is.sunny? What sense has this?
Aug 27, 2014 at 6:42
Yes you can. All an xmlns does is identify what namespace to use. The fact that it sometimes/often is a URL that points to an actual schema is a convention, but is not needed for the functioning of namespaces. All that is needed for the latter is that we all use the same string if we’re talking about the same namespace.
Aug 27, 2014 at 8:08
@Frank: This is not true, changing http://schemas.microsoft.com/winfx/2006/xaml/presentation to http://schemas.apple.com/winfx/2006/xaml/presentation the application does not compile anymore!
Aug 27, 2014 at 10:57
That is because the compiler has an internal string that it uses to find the XAML in your XML. It essentially does document.getElementsByTagNameNS(«http://schemas.microsoft.com/winfx/2006/xaml/presentation», «Window») . By modifying the namespace in your XML, you’ve ensures that the compiler can’t find the XAML anymore. That why I said in my first comment «as long as the string it unique and the same string is used by all parties involved with the XML, it is fine». If you would modify the string in the compiler (not a realistic option here, but at other times it is) it would work again.
Aug 27, 2014 at 13:09
2 Answers 2
The problem is most of wpf developer knows how it works but when you going to explain, it’s become much difficult .. below is my try . due to simplification it become large but i hope if you read to the end, you will understand how the definition thing works ..
Scenario:
I am a wpf beginner developer and searching for a wpf spinner on goggle. i got a link of font.awesome.wpf .. so i started to trying it. below code is written in document to add the spinner ..
Wow great . It’s working fine . .
Suddenly!! i discover that i added a line there
xmlns:fa="http://schemas.fontawesome.io/icons/"
Not something like
xmlns:fa="clr-namespace:FontAwesome.WPF;assembly=FontAwesome.WPF"
then how visual studio knew which dll contain the ImageAwesome class. . I added only FontAwesome.WPF.dll through nuget ..nothing else i did.. no additional xsd or xml file is there.. The schema link(http://schemas.fontawesome.io/icons/) is not available . then how?? . Strange!!
However after 1 hours i ended up with below code..
The noticable part is fa:ImageAwesome and fa:CssClassNameConverter classes. They are from different namespace (using code behind i already checked it).. and i did not specified one extra line to specify any of FontAwesome.WPF or FontAwesome.WPF.Converters namespace.. then how the magic going on!! ..
Solution:
So i downloaded the source code of font.awesome.wpf .. and started search for the text http://schemas.fontawesome.io/icons/ there . and finally i found the below lines in assembly.cs of font.awesome.wpf project..
[assembly: AssemblyVersion("4.5.0.*")] [assembly: AssemblyFileVersion("4.5.0.7")] [assembly: XmlnsPrefix("http://schemas.fontawesome.io/icons/", "fa")] [assembly: XmlnsDefinition("http://schemas.fontawesome.io/icons/", "FontAwesome.WPF")] [assembly: XmlnsDefinition("http://schemas.fontawesome.io/icons/", "FontAwesome.WPF.Converters")]
And the whole thing (the magic trick!!) revealed to me ..
In assembly.cs file the component defined the http://schemas.fontawesome.io/icons/ namespace .. so when i add fontawesome.wpf dll . visual studio got it’s namespace definition using refection .. and so how vs knows where the fa tag refers to . So this is how it resolved to me. 🙂
Some theory
XML namespace name doesn’t match any particular .NET namespace. There are a couple of reasons the creators of XAML chose this design. By convention, XML namespaces are often uniform resource identifiers (URIs) as they are here. These URIs look like they point to a location on the Web, but they don’t. The URI format is used because it makes it unlikely that different organizations will inadvertently create different XML-based languages with the same namespace. Because the domain schemas.microsoft.com is owned by Microsoft, only Microsoft will use it in an XML namespace name.
The other reason that there isn’t a one-to-one mapping between the XML namespaces used in XAML and .NET namespaces is because it would significantly complicate your XAML documents. The problem here is that WPF encompasses well over a dozen namespaces (all of which start with System.Windows). If each .NET namespace had a different XML namespace, you’d need to specify the right namespace for each and every control you use, which quickly gets messy. Instead, the creators of WPF chose to combine all of these .NET namespaces into a single XML namespace. This works because within the different .NET namespaces that are part of WPF, there aren’t any classes that have the same name. The namespace information allows the XAML parser to find the right class. For example, when it looks at the Window and Grid elements, it sees that they are placed in the default WPF namespace. It then searches the corresponding .NET namespaces until it finds System.Windows.Window and System. Windows.Controls.Grid
Как получить удобный доступ к XAML-ресурсам из Code-Behind

Хочу рассказать, как максимально удобно работать с XAML-ресурсами из Code-Behind. В этой статье мы разберемся, как работают пространства имен XAML, узнаем о XmlnsDefinitionAttribute, используем Т4-шаблоны и сгенерируем статичный класс для доступа к XAML-ресурсам.
Введение
При работе с XAML широко используется ResourceDictionary для организации ресурсов: стилей, кистей, конвертеров. Рассмотрим ресурс, объявленный в App.xaml:
При верстке View этот ресурс будет использоваться таким образом:
Когда необходимо использовать тот же самый ресурс из Code-Behind, обычно применяется конструкция:
header.Foreground = (SolidColorBrush)Application.Current.Resources["HeaderBrush"];
В ней есть ряд недостатков: строковой идентификатор (ключ) ресурса увеличивает вероятность ошибки, а при большом количестве ресурсов, скорее всего, придется лезть в xaml и вспоминать этот самый ключ. Еще одна неприятная мелочь — приведение к SolidColorBrush т.к. все ресурсы хранятся в виде object.
Эти недостатки могут быть устранены с помощью кодогенерации, в конечном счете получится такая конструкция:
header.Foreground = AppResources.HeaderBrush;
Сразу оговорюсь, что поскольку цель статьи — показать сам подход, для упрощения я заостряю внимание на одном файле App.xaml, но при желании несложные модификации позволят обработать все XAML-ресурсы в проекте и даже разложить их в отдельные файлы.

Если вы не очень знакомы с T4, можете почитать эту статью.
Используем стандартный для T4-заголовок:
Установка hostSpecific=true необходима для того, чтобы иметь доступ к свойству Host класса TextTransformation, от которого наследуется класс шаблона T4. С помощью Host будет осуществляться доступ к файловой структуре проекта и к некоторым другим необходимым данным.
Все ресурсы будут собраны в один статичный класс со статичными readonly Property. Основной скелет шаблона выглядит так:
using System.Windows; namespace < public static class AppResources < #> > >
Все вспомогательные функции и свойства, задействованные в скрипте, объявляются в секции после основного тела скрипта.
Первое свойство VsProject выбирает проект из Solution, в котором лежит сам скрипт:
private VSProject _vsProject; public VSProject VSProject < get < if (_vsProject == null) < var serviceProvider = (IServiceProvider) Host; var dte = (DTE)serviceProvider.GetService(typeof (DTE)); _vsProject = (VSProject)dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject.Object; >return _vsProject; > >
ProjectDefaultNamespace — пространство имен проекта:
private string _projectDefaultNamespace; public string ProjectDefaultNamespace < get < if (_projectDefaultNamespace == null) _projectDefaultNamespace = VSProject.Project.Properties.Item("DefaultNamespace").Value.ToString(); return _projectDefaultNamespace; >>
Всю основную работу по сбору ресурсов из XAML выполняет ResourcesFromFile(string filename). Чтобы понять принцип его работы, разберем подробней, как в XAML устроены пространства имен, префиксы, а также как они используются.
Пространства имен и префиксы в XAML
Чтобы однозначно указать на определенный тип в C#, необходимо полностью указать имя типа вместе с пространством имен, в котором он объявлен:
var control = new CustomNamespace.CustomControl();
При использовании using приведенную выше конструкцию можно записать короче:
using CustomNamespace; var control = new CustomControl();
Похожим образом работают и пространства имен в XAML. XAML — это подмножество XML и использует правила объявления пространств имен из XML.
Тип CustomControl в XAML будет объявлен так:
В этом случае XAML-анализатор при разборе документа смотрит на префикс local, который описывает, где искать данный тип.
xmlns:local="clr-namespace:CustomNamespace"
Зарезервированное имя атрибута — xmlns — указывает на то, что это объявление пространства имен XML. Имя префикса (в данном случае “local”) может быть любым в рамках правил XML-разметки. А также оно вообще может отсутствовать, тогда объявление пространства имен принимает вид:
xmlns="clr-namespace:CustomNamespace"
Такая запись устанавливает пространство имен по умолчанию для элементов, объявленных без префиксов. Если, например, пространство имен CustomNamespace будет объявлено по умолчанию, то CustomControl можно будет использовать без префикса:
В приведенном выше примере, значение атрибута xmlns содержит метку clr-namespace, сразу за которой следует указание на пространство имен .net. Благодаря этому XAML-анализатор понимает, что ему нужно искать CustomControl в пространстве имен CustomNamespace.
Типы, входящие в состав SDK, например, SolidColorBrush объявляются без префикса.
Это возможно благодаря тому, что в корневом элементе XAML-документа объявлено пространство имен по умолчанию:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Это второй способ объявления пространства имен в XAML. Значение атрибута xmlns — некоторая уникальная строка-alias, она не содержит clr-namespace. Когда XAML-анализатор встречает такую запись, он проверяет .net сборки проекта на атрибут XmlnsDefinitionAttribute.
Атрибут XmlnsDefinitionAttribute переменяется к сборке множество раз описывая пространства имен соответствующие alias-строке:
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows")] [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Media")] [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Shapes")]
Сборка System.WIndows помечена множеством таких атрибутов, таким образом alias schemas.microsoft.com/winfx/2006/xaml/presentation включает в себя множество пространств имен из стандартной SDK таких как: System.Windows, System.Windows.Media и т.д. Это позволяет сопоставить пространство имен XML множеству пространств имен из .net.
Стоит заметить, что, если в двух пространствах имен, объединенных под одним alias, есть типы с одинаковым именем, то возникнет коллизия, и XAML-анализатор не сможет разобрать, откуда ему взять искомый тип.
Итак, теперь мы знаем, что пространства имен XAML сопоставляются с пространствами имен в .net двумя разными способами: один к одному при использовании clr-namespace и один ко многим при использовании alias.
Конструкция xmlns, как правило, встречается в корневом элементе XAML-документа, но на самом деле достаточно, чтобы xmlns был объявлен хотя бы на том же уровне, на котором используется. В случае с CustomControl возможна такая запись:
Все вышеизложенное понадобится для создания скрипта, который может правильно понять XAML-разметку ReosurceDictionary в котором могут лежать разнородные объекты, входящие в SDK, а также компоненты сторонних библиотек, использующих разные способы объявления пространств имен.
Приступим к основной части
Задача по определению полного имени типа по XAML-тегу возложена на интерфейс ITypeResolver:
public interface ITypeResolver
Поскольку есть два вида объявления пространства имен, получилось две реализации данного интерфейса:
public class ExplicitNamespaceResolver : ITypeResolver < private string _singleNamespace; public ExplicitNamespaceResolver(string singleNamespace) < _singleNamespace = singleNamespace; >public string ResolveTypeFullName(string localTagName) < return _singleNamespace + "." + localTagName; >>
Данная реализация обрабатывает случай, когда .net пространство имен указано явно с использованием clr-namespace.
Другой за случай отвечает XmlnsAliasResolver:
public class XmlnsAliasResolver : ITypeResolver < private readonly List> _registeredNamespaces = new List>(); public XmlnsAliasResolver(VSProject project, string alias) < foreach (var reference in project.References.OfType() .Where(r => r.Path.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase))) < try < var assembly = Assembly.ReflectionOnlyLoadFrom(reference.Path); _registeredNamespaces.AddRange(assembly.GetCustomAttributesData() .Where(attr =>attr.AttributeType.Name == "XmlnsDefinitionAttribute" && attr.ConstructorArguments[0].Value.Equals(alias)) .Select(attr => Tuple.Create(attr.ConstructorArguments[1].Value.ToString(), assembly))); > catch <> > > public string ResolveTypeFullName(string localTagName) < return _registeredNamespaces.Select(i =>i.Item2.GetType(i.Item1 + "." + localTagName)).First(i => i != null).FullName; > >
XmlnsAliasResolver регистрирует внутри себя пространства имен, помеченные атрибутом XmlnsDefinitionAttribute с определенным alias, и сборки, в которых они объявлены. Поиск осуществляется в каждом зарегистрированном пространстве имен, пока не будет найден результат.
В реализацию ResolveTypeFullName по желанию можно добавить кэширование найденных типов.
Вспомогательный метод TypeResolvers разбирает XAML-документ, находит все пространства имен и сопоставляет их XML-префиксу, на выходе получается “словарь” Dictionary :
public Dictionary TypeResolvers(XmlDocument xmlDocument) < var resolvers = new Dictionary(); var namespaces = xmlDocument.SelectNodes("//namespace::*").OfType().Distinct().ToArray(); foreach (var nmsp in namespaces) < var match = Regex.Match(string.Format("=\"\"", nmsp.Name, nmsp.Value), @"xmlns:(?\w*)=""((clr-namespace:(?[\w.]*))|([^""]))*"""); var namespaceGroup = match.Groups["namespace"]; var prefix = match.Groups["prefix"].Value; if (string.IsNullOrEmpty(prefix)) prefix = ""; if (resolvers.ContainsKey(prefix)) continue; if (namespaceGroup != null && namespaceGroup.Success) < //Явное указание namespace resolvers.Add(prefix, new ExplicitNamespaceResolver(namespaceGroup.Value)); >else < //Alias который указан в XmlnsDefinitionAttribute resolvers.Add(prefix, new XmlnsAliasResolver(VSProject, nmsp.Value)); >> return resolvers; >
С помощью xpath — «//namespace::*» выбираются все пространства имен, объявленные на любых уровнях документа. Далее каждое пространство имен разбирается регулярным выражением на префикс и на пространство имен .net, указаное после clr-namespace, если оно есть. В соответствие с результатами создается либо ExplicitNamespaceResolver, либо XmlnsAliasResolver и сопоставляется с префиксом или префиксом по умолчанию.
Метод ResourcesFromFile собирает все воедино:
public Resource[] ResourcesFromFile(string filename) < var xmlDocument = new XmlDocument(); xmlDocument.Load(Path.GetDirectoryName(VSProject.Project.FileName) + filename); var typeResolvers = TypeResolvers(xmlDocument); var nsmgr = new XmlNamespaceManager(xmlDocument.NameTable); nsmgr.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml"); var resourceNodes = xmlDocument.SelectNodes("//*[@x:Key]", nsmgr).OfType().ToArray(); var result = new List(); foreach (var resourceNode in resourceNodes) < var prefix = GetPrefix(resourceNode.Name); var localName = GetLocalName(resourceNode.Name); var resourceName = resourceNode.SelectSingleNode("./@x:Key", nsmgr).Value; result.Add(new Resource(resourceName, typeResolvers[prefix].ResolveTypeFullName(localName))); >return result.ToArray(); >
После загрузки XAML-докуменета и инициализации typeResolvers для правильной работы xpath в XmlNamespaceManager добавляется пространство имен schemas.microsoft.com/winfx/2006/xaml, на которое указывают все атрибуты-ключи в ResourceDictionary.
При использовании xpath — «//*[@x:Key]» со всех уровней XAML документа выбираются объекты имеющие атрибут-ключ. Далее скрипт пробегает по всем найденным объектам и с помощью “словаря” typeResolvers ставит в соответствие каждому полное имя .net типа.
На выходе получается массив структур Resource, содержащих в себе все необходимые данные для кодогенерации:
public struct Resource < public string Key < get; private set; >public string Type < get; private set; >public Resource(string key, string type) : this() < Key = key; Type = type; >>
Ну и напоследок метод, который выводит полученный Resource в виде текста:
public void OutputPropery(Resource resource) < #>private static bool _IsLoaded; private static _; public static < get < if (!_IsLoaded) < _= ()Application.Current.Resources[""]; _IsLoaded = true; > return _; > >
Стоит заметить, что свойство Key возвращает значение атрибута-ключа из XAML как есть, и случаи использования ключей с символами, не валидными для объявления свойств в C#, приведут к ошибке. Дабы не усложнять и без того большие куски кода, я намеренно оставляю реализацию получения безопасных для Property имен на ваше усмотрение.
Заключение
Данный скрипт работает в WPF-, Silverlight-, WindowsPhone-проектах. Что касается семейства WindowsRT, UniversalApps, в следующих статьях мы окунемся в XamlTypeInfo.g.cs, поговорим о IXamlMetadataProvider, который пришел на смену XmlnsDefinitionAttribute и заставим скрипт работать с UniversalApps.
Под спойлером вы можете найти полный код скрипта, копируйте в свой проект, используйте с удовольствием.
Полный код скрипта
using System.Windows; namespace < public static class AppResourcess < #> > > private static bool _IsLoaded; private static _; public static < get < if (!_IsLoaded) < _= ()Application.Current.Resources[""]; _IsLoaded = true; > return _; > > private VSProject _vsProject; public VSProject VSProject < get < if (_vsProject == null) < var serviceProvider = (IServiceProvider) Host; var dte = (DTE)serviceProvider.GetService(typeof (DTE)); _vsProject = (VSProject)dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject.Object; >return _vsProject; > > private string _projectDefaultNamespace; public string ProjectDefaultNamespace < get < if (_projectDefaultNamespace == null) _projectDefaultNamespace = VSProject.Project.Properties.Item("DefaultNamespace").Value.ToString(); return _projectDefaultNamespace; >> public struct Resource < public string Key < get; private set; >public string Type < get; private set; >public Resource(string key, string type) : this() < Key = key; Type = type; >> public Resource[] ResourcesFromFile(string filename) < var xmlDocument = new XmlDocument(); xmlDocument.Load(Path.GetDirectoryName(VSProject.Project.FileName) + filename); var typeResolvers = TypeResolvers(xmlDocument); var nsmgr = new XmlNamespaceManager(xmlDocument.NameTable); nsmgr.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml"); var resourceNodes = xmlDocument.SelectNodes("//*[@x:Key]", nsmgr).OfType().ToArray(); var result = new List(); foreach (var resourceNode in resourceNodes) < var prefix = GetPrefix(resourceNode.Name); var localName = GetLocalName(resourceNode.Name); var resourceName = resourceNode.SelectSingleNode("./@x:Key", nsmgr).Value; result.Add(new Resource(resourceName, typeResolvers[prefix].ResolveTypeFullName(localName))); >return result.ToArray(); > public Dictionary TypeResolvers(XmlDocument xmlDocument) < var resolvers = new Dictionary(); var namespaces = xmlDocument.SelectNodes("//namespace::*").OfType().Distinct().ToArray(); foreach (var nmsp in namespaces) < var match = Regex.Match(string.Format("=\"\"", nmsp.Name, nmsp.Value), @"xmlns:(?\w*)=""((clr-namespace:(?[\w.]*))|([^""]))*"""); var namespaceGroup = match.Groups["namespace"]; var prefix = match.Groups["prefix"].Value; if (string.IsNullOrEmpty(prefix)) prefix = ""; if (resolvers.ContainsKey(prefix)) continue; if (namespaceGroup != null && namespaceGroup.Success) < //Явное указание namespace resolvers.Add(prefix, new ExplicitNamespaceResolver(namespaceGroup.Value)); >else < //Alias который указан в XmlnsDefinitionAttribute resolvers.Add(prefix, new XmlnsAliasResolver(VSProject, nmsp.Value)); >> return resolvers; > public interface ITypeResolver < string ResolveTypeFullName(string localTagName); >public class ExplicitNamespaceResolver : ITypeResolver < private string _singleNamespace; public ExplicitNamespaceResolver(string singleNamespace) < _singleNamespace = singleNamespace; >public string ResolveTypeFullName(string localTagName) < return _singleNamespace + "." + localTagName; >> public class XmlnsAliasResolver : ITypeResolver < private readonly List> _registeredNamespaces = new List>(); public XmlnsAliasResolver(VSProject project, string alias) < foreach (var reference in project.References.OfType() .Where(r => r.Path.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase))) < try < var assembly = Assembly.ReflectionOnlyLoadFrom(reference.Path); _registeredNamespaces.AddRange(assembly.GetCustomAttributesData() .Where(attr =>attr.AttributeType.Name == "XmlnsDefinitionAttribute" && attr.ConstructorArguments[0].Value.Equals(alias)) .Select(attr => Tuple.Create(attr.ConstructorArguments[1].Value.ToString(), assembly))); > catch <> > > public string ResolveTypeFullName(string localTagName) < return _registeredNamespaces.Select(i =>i.Item2.GetType(i.Item1 + "." + localTagName)).First(i => i != null).FullName; > > string GetPrefix(string xamlTag) < if (string.IsNullOrEmpty(xamlTag)) throw new ArgumentException("xamlTag is null or empty", "xamlTag"); var strings = xamlTag.Split(new[] , StringSplitOptions.RemoveEmptyEntries); if(strings.Length <2) return ""; return strings[0]; >string GetLocalName(string xamlTag) < if (string.IsNullOrEmpty(xamlTag)) throw new ArgumentException("xamlTag is null or empty", "xamlTag"); var strings = xamlTag.Split(new[] , StringSplitOptions.RemoveEmptyEntries); if(strings.Length <2) return xamlTag; return strings[1]; >#>
- Silverlight
- .NET
- Разработка под Windows Phone
What is meaning of «xmlns:v=urn:schemas-microsoft-com» in HTML5
I happened to find the sentence «xmlns:v=urn:schemas-microsoft-com» as title described Here is source roughly.
As I know xmlns is schema, so to speak metadata. If some element is available in body section, the metadata of this element exist in «schemas.microsft.com» If I develop a html page using «microsoft» schema, all elements used in body section will be referernced by «microsoft» Or, If I use other schema, examply «google» (I don’t know whether this really exist) all element goes same too. Here is my question First, If I use table tag that exist in «microsoft» and «google» schema together Will chrome browser interpret context differently? so comes differnt view? Second, If xmlns is omitted what kind of schema will be used default?
19.2k 3 3 gold badges 23 23 silver badges 44 44 bronze badges
asked Nov 26, 2014 at 5:39
85 1 1 gold badge 1 1 silver badge 10 10 bronze badges
2 Answers 2
The xmlns:* attributes are namespace definitions. Elements and attributes with the prefix/alias «v» or «o» are part of the respective namespace and not part of HTML. If parsed as HTML < 5 the namespaces will be ignored. In HTML 5 here some constructs for specific namespaces (SVG, MathML), but namespace definitions (the xmlns:* attributes) are ignored.
If parsed as XML the attributes define the namespaces. You have to definitions:
- Alias v for urn:schemas-microsoft-com:vml — the Vector Markup Language
- Alias o for urn:schemas-microsoft-com:office:office — MS Office Open XML common attributes
XML namespaces allow to mix different XML formats and avoiding conflicts because of element names.
You file might be generated by MS Office (2003) or a user copied content from Office into it. If here are no elements/attributes starting with v: or o: in your document they don’t do anything.
If the client knows a namespace/format it can interpret the elements. Not only a browser but RSS Readers, Calendars, . If a client does not know a namespace but respects it, it at least knows to ignore the elements/attributes even if they have a name that might be valid in HTML.
XAML и пространства имен

предназначен для определения объектов .NET. Технология XAML применяется во многих областях, однако изначально она разрабатывалась как часть технологии WPF (Windows Presentation Foundations), которая позволяет разработчикам приложений Windows создавать мощные пользовательские интерфейсы. Для создания интерфейсов приложений Silverlight используется тот же стандарт XAML, что и в WPF.
Концептуально язык XAML играет ту же роль, что и HTML или XHTML — он предназначен для определения элементов, размещаемых в области содержимого. Для манипулирования элементами XHTML используется клиентский код JavaScript, а элементами XAML — клиентский код C#. Документы XHTML и XAML основаны на синтаксисе XML и состоят из элементов, вложенных друг в друга в любой последовательности.
Т.к. в WPF и Silverlight используется один и тот же стандарт XAML здесь я не буду описывать структуру и синтаксис этого языка разметки. За более подробными сведениями обращайтесь в раздел «Основы WPF».
Пространства имен XAML
При наличии в файле XAML элемента синтаксический анализатор Silverlight воспринимает его как задание создать экземпляр класса UserControl. Однако он не знает, что это за класс. Ведь, несмотря на то что пространство имен Silverlight содержит только один класс UserControl, нет никакой гарантии того, что разработчик не создал пользовательский класс с таким же именем. Следовательно, чтобы был создан нужный класс, необходим способ задания пространства имен.
В Silverlight классы разрешаются путем добавления пространств имен XML к пространствам имен Silverlight. Специальный атрибут xmlns зарезервирован в XML для объявления пространств имен.
Пространства имен XML объявляются с помощью атрибутов, размещенных в открывающих дескрипторах. Существует соглашение, согласно которому все используемые в документе пространства имен должны быть объявлены в первом дескрипторе. Это существенно облегчает визуальный анализ документа, поскольку избавляет от необходимости искать объявления во всей разметке. После объявления пространства имен его можно использовать в любом месте документа.
Базовые пространства имен Silverlight
Для доступа к важным частям инфраструктуры Silverlight используются следующие пространства имен:
http://schemas.microsoft.com/winfx/2006/xaml/presentation
Базовое пространство имен Silverlight. Оно содержит все классы Silverlight, включая UserControl и Grid. Обычно оно объявляется без префикса, поэтому служит пространством имен, заданным по умолчанию для всего документа. Другими словами, если не указано иное, каждый элемент автоматически располагается в этом пространстве имен.
http://schemas.microsoft.com/winfx/2006/xaml
Пространство имен XAML. Содержит различные средства XAML, позволяющие манипулировать способами интерпретации документа. Данное пространство имен обозначается префиксом х. Это означает, что его можно применить, расположив префикс перед именем элемента ( и х:Class=»имя_класса»).
Информация о пространстве имен позволяет синтаксическому анализатору XAML найти нужный класс. Например, когда синтаксический анализатор видит элементы UserControl и Grid, он знает, что они принадлежат установленному по умолчанию пространству имен http://schemas.microsoft.com/winfx/2006/xaml/presentation. Благодаря этому анализатор находит соответствующие классы System.Windows.UserControl и System.Windows.Controls.Grid.
Пространства имен XML и Silverlight
Пространство имен XML не добавлено в какое-либо одно пространство имен Silverlight. Вместо этого все пространства имен Silverlight находятся в одном и том же пространстве имен XML.
Создатели спецификации XAML предпочли такую архитектуру по нескольким причинам. По общепринятым соглашениям пространства имен XML часто имеют форму URI (как в данном случае). Имена пространств имен выглядят так, будто они указывают на некоторый ресурс в Интернете, но в действительности они ни на что не указывают. Формат URI применяется, чтобы гарантировать уникальность имен, присвоенных разным пространствам имен. Разные организации не имеют одинаковых URI, поэтому они могут присваивать свои URI собственным пространствам имен, не опасаясь, что кто-либо применит такое же имя. Домен schemas.microsoft.com принадлежит компании Microsoft, поэтому только Microsoft может использовать этот URI в пространствах имен XML.
Еще одна причина отсутствия взаимно однозначного соответствия между пространствами имен XML и Silverlight состоит в том, что это существенно усложнило бы документы XAML. Если бы каждое пространство имен Silverlight было представлено как отдельное пространство имен XML вам пришлось бы выбирать правильное пространство имен для каждого элемента управления. Документы XAML и Silverlight быстро превратились бы в беспорядочное месиво. Поэтому создатели Silverlight предпочли отобразить все пространства имен Silverlight, содержащие элементы пользовательских интерфейсов, на единственное пространство имен XML. Это допустимо, поскольку Microsoft гарантирует, что в разных пространствах имен Silverlight никакие два класса не носят одно и то же имя.
Рабочие пространства имен
Кроме базовых, есть два специальных пространства имен, ни одно из которых не является обязательным:
http://schemas.microsoft.com/expression/blend/2008
Пространство имен XAML, связанное с проблемами совместимости разметки с рабочей средой. Используется для сообщения синтаксическому анализатору XAML о том, какую информацию нужно обработать, а какую — проигнорировать.
http://schemas.openxmlformats.org/markup-compatibility/2006
Зарезервированное рабочее пространство имен XAML, поддерживаемое программами Expression Blend и Visual Studio 2010. Используется для установки размеров графической панели для страницы.
В приведенном ниже примере применены оба этих пространства имен:
mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="300">
Свойства DesignWidth и DesignHeight находятся в пространстве имен http://schemas.microsoft.com/expression/blend/2008. Они сообщают рабочей среде, что во время разработки страница должна иметь размеры 400×300 пикселей. Без этого вы были бы вынуждены работать на стесненной графической панели, не отображающей реального вида пользовательского интерфейса, или жестко закодировать размеры с помощью свойств Width и Height (это решение не идеальное, потому что при его использовании размеры страницы не будут изменяться в зависимости от размеров окна браузера).
Свойство Ignorable находится в пространстве имен http://schemas.openxmlformats.org/markup-compatibility/2006. Оно сообщает инструменту XAML о том, что он должен проигнорировать части документа, обозначенные префиксом d и расположенные в пространстве имен http://schemas.microsoft.com/expression/blend/2008. Иными словами, если синтаксический анализатор XAML не поймет слова DesignWidth и DesignHeight, их лучше пропустить, потому что они не так уж важны.
Пользовательские пространства имен
Во многих ситуациях необходим доступ к собственным пространствам имен в файле XAML. Чаще всего он необходим, когда нужно применить пользовательский элемент управления Silverlight (пользовательским называется элемент управления, созданный вами или другим разработчиком, а не компанией Microsoft). В этом случае нужно определить новый префикс пространства имен XML и добавить его в пользовательскую сборку. Это можно сделать следующим образом:
Объявление пространства имен определяет три важных параметра:
Префикс пространства имен XML
Применяется для ссылки на пространство имен в документе XAML. В данном примере задан префикс w, однако можно задать любой идентификатор, не конфликтующий с другими префиксами пространств имен.
Название пространства имен .NET
В данном примере все классы расположены в пространстве имен Widgets. Если есть классы, которые нужно использовать в разных пространствах имен, их можно отобразить на разные или одно и то же пространство имен XML, при условии, что они не конфликтуют с другими именами классов.
Имя сборки
В данном примере классы находятся в сборке WidgetLibrary.dll. Расширение .dll в имя сборки не добавляется.
Отобразив пространство имен .NET на пространство имен XML его можно использовать в любом месте документа XAML. Например, если пространство имен Widgets содержит элемент управления HotButton, создать его экземпляр можно следующим образом: