10 причин моей любви и ненависти к XAML
XAML — неоднозначная технология, которая умудряется дать столько же возможностей, сколько и головной боли. Разбираемся в ее плюсах и минусах.
 
 
Что такое XAML
XAML — это расширенный язык разметки, который используется в .NET. Он схож с HTML, поэтому достаточно прост в освоении. У XAML есть множество качеств, за которые его можно любить, но у каждого такого качества есть обратная сторона, вызывающая ненависть.
Я собрал 5 причин для любви (и столько же — для ненависти) к XAML.
Люблю
Всё отображается так, как напишешь
Можно использовать Grid и выравнивание по горизонтали и вертикали, чтобы создавать адаптивные интерфейсы. Например, минут 15 достаточно, чтобы сверстать приложение с минималистичным дизайном:
 
Интерфейс отображается так, как было написано, а если его растягивать, то он сохранит пропорции:
 
Особенно это удобно для вертикального выравнивания, которое может быть непросто реализовать в HTML и CSS. Здесь это делается с помощью одного свойства VerticalAlignment:
<Border Grid.Row="0" Background="#333">
	<TextBlock Text="Chat" Foreground="#fff" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16pt" FontWeight="DemiBold"/>
</Border>
И самое классное — не нужно адаптировать этот код под разные разрешения или браузеры.
Ненавижу
Чтобы всё отображалось, как ты хочешь, приходится писать много кода
Хотя большая часть задумок реализуется достаточно быстро, код получается громоздким, а иногда все же приходится прибегать к различным хитростям.
Например, в текстовом поле курсор всегда отображается в левом верхнем углу. Это, конечно, можно исправить с помощью Padding, но при изменении размеров поля всё поломается. Поэтому приходится помещать TextBox в контейнер и задавать свойства ему, а само текстовое поле просто выравнивать по центру:
<Border BorderBrush="#444" BorderThickness="1" >
	<TextBox Background="#333" Foreground="#fff" BorderThickness="0" VerticalAlignment="Center" Padding="2"/>
</Border>
Тут HTML выигрывает, потому что в нем не нужно создавать дополнительный элемент.
Однако это всё цветочки по сравнению с тем, что приходится делать, чтобы настроить отображение кнопок (смотрите ниже).
Люблю
Можно использовать стили
В XAML можно использовать стили, дающие большие возможности. Например, есть возможность задать свойства для всех кнопок или списков, а можно создать ключ и выборочно указывать его каким-то элементам.
Стили могут наследоваться, и в них можно менять свойства в зависимости от состояния элемента:
<Window.Resources>
	<Style TargetType="TextBlock">
		<Setter Property="TextBlock.FontFamily" Value="Arial"/>
	</Style>
	<Style x:Key="Button1">
		<EventSetter Event="Button.Click" Handler="Button1_Click"/>
	</Style>
	<Style x:Key="MessagesList">
		<Style.Setters>
			<Setter Property="ListView.Foreground" Value="#fff" />
		</Style.Setters>
		<Style.Triggers>
			<Trigger Property="ListView.IsMouseOver" Value="True">
				<Trigger.Setters>
					<Setter Property="ListView.Foreground" Value="#ccc" />
				</Trigger.Setters>
			</Trigger>
		</Style.Triggers>
	</Style>
</Window.Resources>
Можно даже создать триггер, который будет срабатывать, если пользователь введет определенное значение. Ну и, конечно, можно указывать обработчики событий.
Ненавижу
Иногда со стилями приходится возиться
Есть и обратная сторона. Например, одному элементу можно задать только один стиль. В HTML же можно указывать сразу несколько классов, к которым стиль будет применен.
Также, если у стиля установлен TargetType, ему нельзя указать ключ, и, следовательно, от него нельзя наследовать. Это очень неудобно, если нужно не только задать свойства всем элементам TextBlock, но и наследовать их для дальнейшего использования.
Тогда приходится писать что-то такое:
<Style x:Key="TextBase">
	<Setter Property="TextBlock.Margin" Value="5" />
	<Setter Property="TextBlock.Foreground" Value="#e2e2e2" />
</Style>
<Style BasedOn="{StaticResource TextBase}" TargetType="TextBlock"></Style>
<Style x:Key="TextHeader" BasedOn="{StaticResource TextBase}">
	<Setter Property="TextBlock.FontWeight" Value="DemiBold"/>
</Style>
То есть создавать три стиля вместо двух.
Люблю
Можно использовать шаблоны
Работа со списками в XAML — это чудо. Можно указать как источник элементов коллекцию объектов, а потом вывести их по шаблону:
<ListView ScrollViewer.VerticalScrollBarVisibility="Auto" Background="#444" BorderThickness="0" Name="MessagesListView">
	<ListView.ItemTemplate>
		<DataTemplate>
			<Border Background="#353535" Padding="7" CornerRadius="15" MaxWidth="200">
				<TextBlock Text="{Binding Text}" Foreground="#fff" FontSize="12pt"/>
			</Border>
		</DataTemplate>
	</ListView.ItemTemplate>
</ListView>
Вот сами объекты, коллекция и вывод источника:
public class Message
{
	private string text;
	public Message(string text)
	{
		this.text = text;
	}
	public string Text
	{
		get
		{
			return this.text;
		}
	}
}
public partial class MainWindow : Window
{
	public MainWindow()
	{
		InitializeComponent();
		List<Message> messages = new List<Message>();
		messages.Add(new Message("Hello!"));
		messages.Add(new Message("How are you?"));
		messages.Add(new Message("Long time no see"));
		MessagesListView.ItemsSource = messages;
	}
}
А таким будет вывод:
 
Написав один раз хороший шаблон, можно почти не возвращаться к нему — только если понадобится вывести новое свойство или изменить дизайн.
Ненавижу
Иногда использования шаблонов не избежать
Иногда использование шаблонов — это необходимость, без которой не обойтись. Например, нужно очень постараться, чтобы кнопка при наведении меняла цвет так, как надо:
<Style x:Key="SendButton">
	<Style.Setters>
		<Setter Property="Border.Margin" Value="1" />
		<Setter Property="Border.Background" Value="#333" />
		<Setter Property="TextBlock.Foreground" Value="#fff" />
		<Setter Property="TextBlock.FontWeight" Value="DemiBold"/>
		<Setter Property="TextBlock.VerticalAlignment" Value="Center"/>
		<Setter Property="TextBlock.TextAlignment" Value="Center"/>
		<Setter Property="Border.Padding" Value="10, 5" />
		<Setter Property="Button.Template">
			<Setter.Value>
				<ControlTemplate>
					<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Border.Padding}">
						<TextBlock Text="{TemplateBinding Button.Content}"/>
					</Border>
				</ControlTemplate>
			</Setter.Value>
		</Setter>
	</Style.Setters>
	<Style.Triggers>
		<Trigger Property="Control.IsMouseOver" Value="true">
			<Setter Property="Button.Background" Value="#444"/>
		</Trigger>
	</Style.Triggers>
</Style>
Это очень большой код, поэтому бесит, когда приходится писать его в каждом проекте. Для сравнения, вот как это делается в CSS:
.button
{
	background: #333;
}
.button:hover
{
	background: #444;
}
Люблю
Можно использовать привязку данных
Еще одна крутая штука — привязка данных. Можно в качестве значения текстового поля указать название свойства объекта — и, когда пользователь изменит текст, изменится и объект:
<TextBox Text="{Binding Name}" Background="#333" Foreground="#fff" BorderThickness="0" VerticalAlignment="Center" Padding="2"/>
Можно привязать это же свойство к другому элементу, который тоже будет меняться:
<TextBlock Text="{Binding Name, Mode=OneWay}" Foreground="#fff" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16pt" FontWeight="DemiBold"/>
И вот что получится в результате:

Ненавижу
В некоторые аспекты сложно вникнуть
Привязка данных позволяет значительно сократить код и избавить разработчика от решения многих задач. Но проблема в том, что использовать привязку бывает очень сложно. Чаще всего потому, что не всегда понятно, из-за чего вывод работает некорректно. А причин может быть много:
- неправильно указана привязка;
- не указан DataContext;
- передается пустой объект и так далее.
Также каждый раз приходится имплементировать интерфейс INotifyPropertyChanged и писать повторяющийся код для каждого класса, об изменении которого нужно уведомлять.
public class User : INotifyPropertyChanged
{
	private string name;
	public User(string name)
	{
		this.name = name;
	}
	public string Name
	{
		get
		{
			return this.name;
		}
		set
		{
			this.name = value;
			NotifyPropertyChanged();
		}
	}
	public void NotifyPropertyChanged(string propertyName = "")
	{
		PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
	}
	public event PropertyChangedEventHandler PropertyChanged;
}
Люблю
Один язык разметки для всех платформ
Еще одна крутая особенность — кроссплатформенность. XAML используется не только в WPF, но и в Xamarin.Forms. Это позволяет разработчикам ПО для компьютеров быстро начать создавать мобильные приложения.
Так, можно один раз написать интерфейс, который будет работать на Android, iOS и UWP (Windows 10). При этом XAML скомпилируется в нативный код для этих платформ.
Ненавижу
XAML в WPF! = XAML в Xamarin.Forms
Только начинаешь вникать в Xamarin.Forms, как XAML делает удар под дых — это не тот XAML, который ты любишь и знаешь.
Можно, конечно, стерпеть, что у некоторых элементов другие названия. Например, что StackPanel превращается в StackLayout. Можно даже привыкнуть к тому, что для одних целей используются разные элементы. Например, в Xamarin.Forms текст выводится с помощью Label, а не TextBlock.
Но самое интересное начинается, когда пытаешься добавить привязку данных, потому что она делается совсем не так, как ты привык. Можно потратить несколько часов, пока не осознаешь, что ты пытаешься использовать MVVM, а нужно — MVVMCross.
Заключение
XAML — это крутая технология, которую есть за что любить, но есть и за что ненавидеть. Поэтому разработка превращается в эмоциональные качели: сначала ты счастлив, что всё так просто и удобно, а потом тратишь на реализацию небольшой, казалось бы, фичи несколько часов.
Однако, проработав достаточно долго как с HTML, так и с XAML, я все равно выберу второй. Потому что с ним я каждый раз уверен, что все работает так, как мне нужно, и никак не зависит от внешних факторов.
 Все
                                Все
                             Истории
                                        Истории Дизайн
                                    Дизайн Код
                                    Код Геймдев
                                    Геймдев Бизнес
                                    Бизнес Маркетинг
                                    Маркетинг Управление
                                    Управление Кино
                                    Кино Музыка
                                    Музыка Проектная фотография
                                    Проектная фотография Развитие
                                    Развитие Здоровье
                                    Здоровье Деньги
                                    Деньги Образование
                                    Образование EdTech
                                    EdTech Корп. обучение
                                    Корп. обучение Блог Skillbox
                                    Блог Skillbox Глоссарий
                                        Глоссарий Спецпроекты
                                        Спецпроекты Профориентация
                                        Профориентация 
                                     
			 
                     
     
                                     
                                     
                                     
                                    