Avalonia con estilo

Los estilos, por defecto, que en wpf, que en Avalonia, son extremadamente neutrales y están lejos de ser siempre adecuados para las tareas que necesitamos, y pocos desarrolladores novatos son amigos de ellos. En este artículo, me gustaría hablar sobre los conceptos básicos del trabajo con estilos y mostrar algunos ejemplos interesantes.



¿Por qué necesitamos estilos en el marco de Avalonia?

  1. Los estilos dan más libertad al personalizar elementos;
  2. Permitir no duplicar descripciones de elementos;
  3. Separe el marcado en sí y su diseño.

Un par de ejemplos


Para una mejor comprensión de los estilos, primero pasamos a un ejemplo:

Botón redondeado (algo así como un gnomo de ubuntu)
Para hacer esto, crearemos en la plantilla estándar ( cómo crear una plantilla ) un marcado simple de la pila del panel y un par de botones.

<StackPanel> <Button Margin="20" Content="Btn" /> <Button Margin="20" Content="Style Btn" /> </StackPanel> 

Ahora podemos manejar los botones con el fondo principal y el color de fuente, pero luego tendremos que duplicar el código. El estilo ayudará a evitar esta repetición.

Agregue el estilo apropiado a la ventana:

  <Window.Styles> <Style Selector="Button"> <Setter Property="Foreground" Value="#FFFFFFFF" /> <Setter Property="BorderThickness" Value="2" /> <Setter Property="Background" Value="#FFDD4812" /> <Setter Property="BorderBrush" Value="#FFFFFFFF" /> </Style> </Window.Styles> 



Obtenemos algo similar, pero sería bueno redondear los bordes. Desafortunadamente, no importa cómo lo intentemos, es imposible redondear los bordes del botón, pero puede redondear los bordes de la plantilla responsable de mostrar el botón. Para hacer esto, agregue otro estilo:

 <Style Selector="Button /template/ ContentPresenter"> <Setter Property="CornerRadius" Value="10" /> </Style> 



Resultó casi similar, pero hay un problema: cuando pasas el cursor sobre el botón, aparece un marco gris (hola desde el estilo estándar).



Para hacer esto, vaya a la pseudo-clase css : pointerover y agregue otro estilo:

  <Style Selector="Button:pointerover /template/ ContentPresenter"> <Setter Property="BorderBrush" Value="#FFDD4812" /> </Style> 



Mucho mejor

Pero, ¿qué sucede si quiero aplicar estilos solo a botones específicos?

Agregue un botón más a la plantilla y escriba en los botones que queremos "decorar" el atributo Clases .

  <StackPanel> <Button Margin="20" Content="Btn" /> <Button Margin="20" Classes="btn" Content="Style Btn" /> <Button Margin="20" Classes="btn" Content="Style Btn" /> </StackPanel> 

Y le indicaremos a los estilos que necesitamos influir solo en ciertas clases:

 <Style Selector="Button.btn /template/ ContentPresenter"> <Setter Property="CornerRadius" Value="10" /> </Style> <Style Selector="Button.btn"> <Setter Property="Foreground" Value="#FFFFFFFF" /> <Setter Property="BorderThickness" Value="2" /> <Setter Property="Background" Value="#FFDD4812" /> <Setter Property="BorderBrush" Value="#FFFFFFFF" /> </Style> <Style Selector="Button:pointerover.btn /template/ ContentPresenter"> <Setter Property="BorderBrush" Value="#FFDD4812" /> </Style> 



Todo el código de la ventana
 <Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:Wind1.ViewModels;assembly=Wind1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Wind1.Views.MainWindow" Icon="/Assets/avalonia-logo.ico" Title="Wind1"> <Window.Styles> <Style Selector="Button.btn /template/ ContentPresenter"> <Setter Property="CornerRadius" Value="10" /> </Style> <Style Selector="Button.btn"> <Setter Property="Foreground" Value="#FFFFFFFF" /> <Setter Property="BorderThickness" Value="2" /> <Setter Property="Background" Value="#FFDD4812" /> <Setter Property="BorderBrush" Value="#FFFFFFFF" /> </Style> <Style Selector="Button:pointerover.btn /template/ ContentPresenter"> <Setter Property="BorderBrush" Value="#FFDD4812" /> </Style> </Window.Styles> <StackPanel> <Button Margin="20" Content="Btn" /> <Button Margin="20" Classes="btn" Content="Style Btn" /> <Button Margin="20" Classes="btn" Content="Style Btn" /> </StackPanel> </Window> 


Otro ejemplo de estilo interesante.
La casilla de verificación estándar tiene este aspecto:



Ligeramente mejorado es similar a Android (un poco)



Algo de magia
 <Window.Styles> <Style Selector="CheckBox.uberbox"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <Grid> <Border Background="#b0b0b0" Padding="5" BorderBrush="#303030" CornerRadius="5"> <Grid> <Grid Classes="unchecked" ColumnDefinitions=" Auto, Auto"> <Border Width="20" Height="20" Background="Blue" CornerRadius="5" /> <TextBlock FontWeight="Bold" Margin="5,0,0,0" Grid.Column="1">0FF </TextBlock> </Grid> <Grid Classes="checked" ColumnDefinitions=" Auto, Auto"> <Border Grid.Column="1" Width="20" Height="20" Background="Red" CornerRadius="5" /> <TextBlock FontWeight="Bold" Margin="0,0,5,0"> ON </TextBlock> </Grid> </Grid> </Border> <Border Classes="fade" Background="White" CornerRadius="5" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style Selector="CheckBox.uberbox /template/ Grid.checked"> <Setter Property="Opacity" Value="0" /> </Style> <Style Selector="CheckBox.uberbox:checked /template/ Grid.checked"> <Setter Property="Opacity" Value="1" /> </Style> <Style Selector="CheckBox.uberbox:checked /template/ Grid.unchecked"> <Setter Property="Opacity" Value="0" /> </Style> <Style Selector="CheckBox.uberbox /template/ Border.fade"> <Setter Property="Opacity" Value="0" /> </Style> <Style Selector="CheckBox.uberbox:pointerover /template/ Border.fade"> <Setter Property="Opacity" Value="0.2" /> </Style> </Window.Styles> <StackPanel> <CheckBox Classes="uberbox" Margin="10" /> </StackPanel> 



Donde usar estilos


Los estilos se pueden usar tanto dentro de la ventana (como lo hicimos en los ejemplos escritos anteriormente),
y dentro de toda la aplicación (entonces el estilo se aplicará en todas las ventanas).

Para hacer esto, agregue el estilo al archivo App.xaml.

  <Application.Styles> <StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/> <StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/> <Style Selector="Button"> <Setter Property="Background" Value="Blue"></Setter> </Style> </Application.Styles> 

Mayor separación


Con la complicación del código, ya no queremos mantener los estilos dentro del diseño de la ventana, sino que preferimos colocarlos en un archivo separado:



Para hacer esto, cree el directorio de estilos y coloque nuestros estilos allí en forma de archivos xml o xaml, agregando las instrucciones del espacio de nombres:

 <Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=netstandard"> <Style Selector="Button /template/ ContentPresenter"> <Setter Property="CornerRadius" Value="10" /> </Style> <Style Selector="Button"> <Setter Property="Foreground" Value="#FFFFFFFF" /> <Setter Property="BorderThickness" Value="2" /> <Setter Property="Background" Value="#FFDD4812" /> <Setter Property="BorderBrush" Value="#FFFFFFFF" /> </Style> <Style Selector="Button:pointerover /template/ ContentPresenter"> <Setter Property="BorderBrush" Value="#FFDD4812" /> </Style> </Styles> 

Agregue nuevos recursos al archivo del proyecto (* .csproj):

  <AvaloniaResource Include="Styles\**" /> 

Y conéctelos usando la etiqueta StyleInclude

 <Window.Styles> <StyleInclude Source="/Styles/Style.xml"/> </Window.Styles> 

Pero a veces esto no es suficiente, y quiero poner los estilos en un dll separado para usar en todos mis proyectos.

Para hacer esto, cree una ClassLibrary y brinde soporte para nuestros archivos futuros como avaloniya de recursos:

  <ItemGroup> <AvaloniaResource Include="**\*.xaml"> <SubType>Designer</SubType> </AvaloniaResource> </ItemGroup> <ItemGroup> <AvaloniaResource Include="**\*.xml"> <SubType>Designer</SubType> </AvaloniaResource> </ItemGroup> 

Ahora agregue el conocido Styles.xml y 2 archivos nuevos más al proyecto:



En el archivo xaml, debe especificar el espacio de nombres y la clase a la que pertenece, así como la conexión del recurso necesario:

 <Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="ClassLibrary1.DarkCustom"> <StyleInclude Source="avares://ClassLibrary1/Style.xml"/> </Styles> 

Y en el archivo cs definimos que este es un estilo y no más:

 namespace ClassLibrary1 { public class DarkCustom:Styles { } } 

Agregue una dependencia a nuestra biblioteca y vuelva a conectar el estilo, especificando el estilo como un recurso de avalonia usando StyleInclude y

  <Window.Styles> <StyleInclude Source="avares://ClassLibrary1/DarkCustom.xaml"/> </Window.Styles> 

Algunos mas utiles


Asegúrese de revisar el tutorial oficial de estilo Avalonia ( tyk )
Puede obtener ideas básicas sobre cómo escribir un estilo para este o aquel elemento aquí ( tyk )
Y si no tiene tiempo / ganas de crear su propio estilo, puede usar este maravilloso generador de estilos ( tyk )



Me gustaría dar las gracias a ForNeVer kekekeks worldbeater

Y tenga en cuenta que el soporte para c # se puede encontrar aquí , y para Avalonia aquí .

Source: https://habr.com/ru/post/471046/


All Articles