|
1 | 1 | # XAML Essentials |
2 | 2 |
|
3 | | -## Importing a namespace |
| 3 | +Each tag in XAML file is of `AvaloniaObject`, it can be of `Control` or something else but inherits from `AvaloniaObject`. |
4 | 4 |
|
5 | | -The semantic of `xmlns:x` basically means importing a namespace as an alias named `x`. |
6 | | -Then we can use `:` to access the members of the namespace. |
7 | | -`x:Class` binds the code behind(`.axaml.cs`) the AXAML(not the ViewModel!). |
| 5 | +::: code-group |
8 | 6 |
|
9 | | -```xml |
| 7 | +```xml [App.axaml] |
| 8 | +<!-- Application is AvaloniaObject but not a Control --> <!-- [!code highlight] --> |
10 | 9 | <Application xmlns="https://github.com/avaloniaui" |
11 | 10 | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
12 | | - x:Class="AvaloniaApplication.App" |
13 | | - xmlns:local="using:AvaloniaApplication" |
| 11 | + x:Class="MyApp.App" |
| 12 | + xmlns:local="using:MyApp" |
14 | 13 | RequestedThemeVariant="Default"> |
15 | | - <!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. --> |
| 14 | + <Application.DataTemplates> |
| 15 | + <local:ViewLocator/> |
| 16 | + </Application.DataTemplates> |
| 17 | + <Application.Styles> |
| 18 | + <FluentTheme /> |
| 19 | + </Application.Styles> |
16 | 20 | </Application> |
17 | 21 | ``` |
| 22 | +::: |
| 23 | + |
| 24 | +## XAML Namespace |
18 | 25 |
|
19 | | -## Spreading Namespace |
| 26 | +XAML namespace was a feature inherited from xml, it allows to import namespaces at any level of element, and all of its child elements within the scope can access the namespace. |
| 27 | +A namespace follows syntax of `xmlns[:<alias>]`, where `<alias>` is available as identifier in scope, either **as attribute name or a interpolated uri using another namespace alias.** |
20 | 28 |
|
21 | | -The default namespace is imported without name, which mean its members are imported globally in this AXAML file, can be accessed them without any prefix. |
22 | | -Generally the default is avalonia namespace which contains built-in components like `Button`, `TextBlock`. |
| 29 | +> [!NOTE] |
| 30 | +> Namespace is **not order-sensitive**, they're structural. |
23 | 31 |
|
24 | 32 | ```xml |
25 | | -<Application xmlns="https://github.com/avaloniaui" <!-- [!code highlight] --> |
26 | | - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
27 | | - x:Class="AvaloniaApplication.App" |
28 | | - xmlns:local="using:AvaloniaApplication" |
29 | | - RequestedThemeVariant="Default"> |
30 | | - <!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. --> |
31 | | -</Application> |
| 33 | +<MyElement xmlns:vm="using:MyApp.ViewModels" |
| 34 | + x:DataType="vm:MainWindowViewModel"> <!-- use vm alias in another namespace --> <!-- [!code highlight] --> |
| 35 | + <BarElement xmlns:BarElement="MyElement.BarElement" /> <!-- namespace can be imported in any level --> <!-- [!code highlight] --> |
| 36 | +</MyElement> |
32 | 37 | ``` |
33 | 38 |
|
34 | | -## Import from Project Namespace |
| 39 | +### Default Namespace |
35 | 40 |
|
36 | | -`using:<namespace>` imports the namespace from **specific project** with the alias name `local` |
| 41 | +Default namespace is a shorthand without alias name that emits members into current scope. |
| 42 | +The default namespace in xaml files is particularly a url, but compiler is not going to read any content of it, instead it's simply a unique identifier used as a key to a specific internal mapping. |
37 | 43 |
|
38 | 44 | ```xml |
39 | | -<Application xmlns="https://github.com/avaloniaui" |
40 | | - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
41 | | - x:Class="AvaloniaApplication.App" |
42 | | - xmlns:local="using:AvaloniaApplication" <!-- [!code highlight] --> |
43 | | - RequestedThemeVariant="Default"> |
44 | | - <!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. --> |
| 45 | +<Foo xmlns="https://github.com/avaloniaui" /> |
| 46 | +``` |
45 | 47 |
|
46 | | - <Application.DataTemplates> |
47 | | - <local:ViewLocator/> <!-- use `local` here to access types from it --> <!-- [!code highlight] --> |
48 | | - </Application.DataTemplates> |
49 | | -</Application> |
| 48 | +### Conventional Namespaces |
| 49 | + |
| 50 | +- `xmlns:x`: a namespace of common XAML directives, see [XAML Directives](#xaml-directives) |
| 51 | + ```xml |
| 52 | + <Foo xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" /> |
| 53 | + ``` |
| 54 | +- `xmlns:d` |
| 55 | +- `xmlns:vm` |
| 56 | +- `xmlns:mc` |
| 57 | + |
| 58 | +## XAML Directives |
| 59 | + |
| 60 | +`xmlns:x` contains common directives of XAML elements to bind special context for the xaml file, such its code-behind class and view model. |
| 61 | +Each child element within the scope can access it. |
| 62 | + |
| 63 | +- `x:Class`: the class of control presented as xaml element. |
| 64 | +- `x:DataType`: the `DataContext`(aka ViewModel in MVVM) for current control. |
| 65 | +- `x:Name`: name of the instance of control within the code-behind class. |
| 66 | + - XAML compiler would generate an instance by that name for your code-behind class. |
| 67 | + - avalonia has a `StyledElement.Name` property available, which is an equivalence of `x:Name` |
| 68 | +- `x:Static`: accessor for **static members in assembly** |
| 69 | +```xml |
| 70 | + <Window.Resources> |
| 71 | + <SolidColorBrush Color="{x:Static Colors.Aqua}"></SolidColorBrush> <!-- [!code highlight] --> |
| 72 | + </Window.Resources> |
| 73 | +``` |
| 74 | +- `x:Key`: similar to `x:Name` but for static identifier in resource dictionary |
| 75 | + |
| 76 | +::: code-group |
| 77 | +```xml [XAML] |
| 78 | +<Window xmlns="https://github.com/avaloniaui" |
| 79 | + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" <!-- [!code highlight] --> |
| 80 | + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| 81 | + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| 82 | + xmlns:vm="using:MyApp.ViewModels" |
| 83 | + mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
| 84 | + x:Class="MyApp.Views.MainWindow" <!-- [!code highlight] --> |
| 85 | + x:DataType="vm:MainWindowViewModel" <!-- [!code highlight] --> |
| 86 | + Title="MyApp"> |
| 87 | + |
| 88 | + <StackPanel> |
| 89 | + <TextBlock x:Name="MyTextBlock" /> <!-- [!code highlight] --> |
| 90 | + <TextBlock Name="MyAnotherTextBlock" /> <!-- this is equivalent way to declare the field --> <!-- [!code highlight] --> |
| 91 | + </StackPanel> |
| 92 | +</Window> |
| 93 | +``` |
| 94 | +```cs [code-behind] |
| 95 | +using Avalonia.Controls; |
| 96 | + |
| 97 | +namespace MyApp.Views; |
| 98 | +public partial class MainWindow : Window { |
| 99 | + public MainWindow() { |
| 100 | + InitializeComponent(); |
| 101 | + // access the control instance declared in XAML |
| 102 | + this.MyTextBlock.Text = nameof(MyTextBlock); // [!code highlight] |
| 103 | + this.MyAnotherTextBlock.Text = nameof(MyAnotherTextBlock); // [!code highlight] |
| 104 | + } |
| 105 | +} |
50 | 106 | ``` |
| 107 | +::: |
| 108 | + |
| 109 | +## Property Syntax |
| 110 | + |
| 111 | +A property can be assigned by **attribute syntax** or a nesting element(when the property is a structural element) |
| 112 | + |
| 113 | +```xml |
| 114 | +<MyWindow FooProperty="FooProperty"></MyWindow> |
| 115 | +<!-- equivalent to --> |
| 116 | +<MyWindow> |
| 117 | + <MyWindow.FooProperty>FooProperty</MyWindow.FooProperty> |
| 118 | +</MyWindow> |
| 119 | +``` |
| 120 | + |
| 121 | +## Implicit Bindings |
| 122 | + |
| 123 | +- `ContentControl.Content`: xaml compiler would recognize the first(and only allow one) element as the value of `Content`. |
| 124 | +- `ItemsControl.Items` |
| 125 | + |
| 126 | +> [!NOTE] |
| 127 | +> `ContentControl.Content` and `ItemsControl.Items` are all marked by `[Avalonia.Metadata.ContentAttribute]` |
| 128 | +>```cs |
| 129 | +>public class ContentControl |
| 130 | +> : TemplatedControl, |
| 131 | +> IContentControl, |
| 132 | +> IContentPresenterHost { |
| 133 | +> /** ... **/ |
| 134 | +> public static readonly StyledProperty<object?> ContentProperty = |
| 135 | +> AvaloniaProperty.Register<ContentControl, object?>(nameof(Content)); |
| 136 | +> |
| 137 | +> [Content] // [!code highlight] |
| 138 | +> [DependsOn(nameof(ContentTemplate))] |
| 139 | +> public object? Content { |
| 140 | +> get => GetValue(ContentProperty); // ContentProperty is of type AvaloniaProperty // [!code highlight] |
| 141 | +> set => SetValue(ContentProperty, value); |
| 142 | +> } |
| 143 | +> /** ... **/ |
| 144 | +>} |
| 145 | +>``` |
0 commit comments