|
|
@@ -2,8 +2,6 @@
|
|
|
:----------------:|:----------:|:----------------:
|
|
|
[Вывод данных согласно макета (ListBox, Image)](./articles/wpf_listbox.md) | [Содержание](../readme.md#тема-8-оконные-приложения) | [Создание окон. Модальные окна](./wpf_window.md)
|
|
|
|
|
|
->Два инициативных студента по итогам прошлой лекции решили сделать переключение вида отображения "список" и "плитка" кнопкой. Нарыли интересную тему про стили...
|
|
|
-
|
|
|
# [Стили и темы](https://metanit.com/sharp/wpf/10.php)
|
|
|
|
|
|
## Стили
|
|
|
@@ -37,85 +35,77 @@
|
|
|
Здесь обе кнопки применяют ряд свойств с одними и теми же значениями. Однако в данном случае мы вынуждены повторяться. Частично, проблему могло бы решить использование ресурсов:
|
|
|
|
|
|
```xml
|
|
|
-<Window
|
|
|
- ...
|
|
|
->
|
|
|
- <Window.Resources>
|
|
|
- <FontFamily
|
|
|
- x:Key="buttonFont">
|
|
|
- Verdana
|
|
|
- </FontFamily>
|
|
|
- <SolidColorBrush
|
|
|
- Color="White"
|
|
|
- x:Key="buttonFontColor" />
|
|
|
- <SolidColorBrush
|
|
|
- Color="Black"
|
|
|
- x:Key="buttonBackColor" />
|
|
|
- <Thickness
|
|
|
- x:Key="buttonMargin"
|
|
|
- Bottom="10"
|
|
|
- Left="10"
|
|
|
- Top="10"
|
|
|
- Right="10" />
|
|
|
- </Window.Resources>
|
|
|
+<Window.Resources>
|
|
|
+ <FontFamily
|
|
|
+ x:Key="buttonFont">
|
|
|
+ Verdana
|
|
|
+ </FontFamily>
|
|
|
+ <SolidColorBrush
|
|
|
+ Color="White"
|
|
|
+ x:Key="buttonFontColor" />
|
|
|
+ <SolidColorBrush
|
|
|
+ Color="Black"
|
|
|
+ x:Key="buttonBackColor" />
|
|
|
+ <Thickness
|
|
|
+ x:Key="buttonMargin"
|
|
|
+ Bottom="10"
|
|
|
+ Left="10"
|
|
|
+ Top="10"
|
|
|
+ Right="10" />
|
|
|
+</Window.Resources>
|
|
|
|
|
|
- <StackPanel
|
|
|
- x:Name="buttonsStack"
|
|
|
- Background="Black" >
|
|
|
- <Button
|
|
|
- x:Name="button1"
|
|
|
- Content="Кнопка 1"
|
|
|
- Margin="{StaticResource buttonMargin}"
|
|
|
- FontFamily="{StaticResource buttonFont}"
|
|
|
- Foreground="{StaticResource buttonFontColor}"
|
|
|
- Background="{StaticResource buttonBackColor}" />
|
|
|
- <Button
|
|
|
- x:Name="button2"
|
|
|
- Content="Кнопка 2"
|
|
|
- Margin="{StaticResource buttonMargin}"
|
|
|
- FontFamily="{StaticResource buttonFont}"
|
|
|
- Foreground="{StaticResource buttonFontColor}"
|
|
|
- Background="{StaticResource buttonBackColor}"/>
|
|
|
- </StackPanel>
|
|
|
-</Window>
|
|
|
+<StackPanel
|
|
|
+ x:Name="buttonsStack"
|
|
|
+ Background="Black" >
|
|
|
+ <Button
|
|
|
+ x:Name="button1"
|
|
|
+ Content="Кнопка 1"
|
|
|
+ Margin="{StaticResource buttonMargin}"
|
|
|
+ FontFamily="{StaticResource buttonFont}"
|
|
|
+ Foreground="{StaticResource buttonFontColor}"
|
|
|
+ Background="{StaticResource buttonBackColor}" />
|
|
|
+ <Button
|
|
|
+ x:Name="button2"
|
|
|
+ Content="Кнопка 2"
|
|
|
+ Margin="{StaticResource buttonMargin}"
|
|
|
+ FontFamily="{StaticResource buttonFont}"
|
|
|
+ Foreground="{StaticResource buttonFontColor}"
|
|
|
+ Background="{StaticResource buttonBackColor}"/>
|
|
|
+</StackPanel>
|
|
|
```
|
|
|
|
|
|
Однако в реальности код раздувается, опть же приходится писать много повторяющейся информации. И в этом плане стили предлагают более элегантное решение:
|
|
|
|
|
|
```xml
|
|
|
-<Window
|
|
|
- ...
|
|
|
->
|
|
|
- <Window.Resources>
|
|
|
- <Style x:Key="BlackAndWhite">
|
|
|
- <Setter
|
|
|
- Property="Control.FontFamily"
|
|
|
- Value="Verdana" />
|
|
|
- <Setter
|
|
|
- Property="Control.Background"
|
|
|
- Value="Black" />
|
|
|
- <Setter
|
|
|
- Property="Control.Foreground"
|
|
|
- Value="White" />
|
|
|
- <Setter
|
|
|
- Property="Control.Margin"
|
|
|
- Value="10" />
|
|
|
- </Style>
|
|
|
- </Window.Resources>
|
|
|
+<Window.Resources>
|
|
|
+ <Style x:Key="BlackAndWhite">
|
|
|
+ <Setter
|
|
|
+ Property="Control.FontFamily"
|
|
|
+ Value="Verdana" />
|
|
|
+ <Setter
|
|
|
+ Property="Control.Background"
|
|
|
+ Value="Black" />
|
|
|
+ <Setter
|
|
|
+ Property="Control.Foreground"
|
|
|
+ Value="White" />
|
|
|
+ <Setter
|
|
|
+ Property="Control.Margin"
|
|
|
+ Value="10" />
|
|
|
+ </Style>
|
|
|
+</Window.Resources>
|
|
|
|
|
|
- <StackPanel
|
|
|
- x:Name="buttonsStack"
|
|
|
- Background="Black" >
|
|
|
- <Button
|
|
|
- x:Name="button1"
|
|
|
- Content="Кнопка 1"
|
|
|
- Style="{StaticResource BlackAndWhite}" />
|
|
|
- <Button
|
|
|
- x:Name="button2"
|
|
|
- Content="Кнопка 2"
|
|
|
- Style="{StaticResource BlackAndWhite}"/>
|
|
|
- </StackPanel>
|
|
|
-</Window>
|
|
|
+<StackPanel
|
|
|
+ x:Name="buttonsStack"
|
|
|
+ Background="Black" >
|
|
|
+ <Button
|
|
|
+ x:Name="button1"
|
|
|
+ Content="Кнопка 1"
|
|
|
+ Style="{StaticResource BlackAndWhite}" />
|
|
|
+ <Button
|
|
|
+ x:Name="button2"
|
|
|
+ Content="Кнопка 2"
|
|
|
+ Style="{StaticResource BlackAndWhite}"/>
|
|
|
+</StackPanel>
|
|
|
```
|
|
|
|
|
|
Результат будет тот же, однако теперь мы избегаем ненужного повторения. Более того теперь мы можем управлять всеми нужными нам свойствами как единым целым - одним стилем.
|
|
|
@@ -169,43 +159,42 @@
|
|
|
Hам необязательно прописывать для всех кнопок стиль. Мы можем в самом определении стиля с помощью свойства _TargetType_ задать тип элементов. В этом случае стиль будет автоматически применяться ко всем кнопкам в окне:
|
|
|
|
|
|
```xml
|
|
|
-<Window ...>
|
|
|
- <Window.Resources>
|
|
|
- <Style
|
|
|
- TargetType="Button">
|
|
|
- <Setter
|
|
|
- Property="FontFamily"
|
|
|
- Value="Verdana" />
|
|
|
- <Setter
|
|
|
- Property="Background"
|
|
|
- Value="Black" />
|
|
|
- <Setter
|
|
|
- Property="Foreground"
|
|
|
- Value="White" />
|
|
|
- <Setter
|
|
|
- Property="Margin"
|
|
|
- Value="10" />
|
|
|
- </Style>
|
|
|
- </Window.Resources>
|
|
|
+<Window.Resources>
|
|
|
+ <Style
|
|
|
+ TargetType="Button"
|
|
|
+ >
|
|
|
+ <Setter
|
|
|
+ Property="FontFamily"
|
|
|
+ Value="Verdana" />
|
|
|
+ <Setter
|
|
|
+ Property="Background"
|
|
|
+ Value="Black" />
|
|
|
+ <Setter
|
|
|
+ Property="Foreground"
|
|
|
+ Value="White" />
|
|
|
+ <Setter
|
|
|
+ Property="Margin"
|
|
|
+ Value="10" />
|
|
|
+ </Style>
|
|
|
+</Window.Resources>
|
|
|
|
|
|
- <StackPanel
|
|
|
- x:Name="buttonsStack"
|
|
|
- Background="Black" >
|
|
|
- <Button
|
|
|
- x:Name="button1"
|
|
|
- Content="Кнопка 1" />
|
|
|
- <Button
|
|
|
- x:Name="button2"
|
|
|
- Content="Кнопка 2" />
|
|
|
- </StackPanel>
|
|
|
-</Window>
|
|
|
+<StackPanel
|
|
|
+ x:Name="buttonsStack"
|
|
|
+ Background="Black" >
|
|
|
+ <Button
|
|
|
+ x:Name="button1"
|
|
|
+ Content="Кнопка 1" />
|
|
|
+ <Button
|
|
|
+ x:Name="button2"
|
|
|
+ Content="Кнопка 2" />
|
|
|
+</StackPanel>
|
|
|
```
|
|
|
|
|
|
Причем в этом случае нам уже не надо указывать у стиля ключ `x:Key` несмотря на то, что это ресурс.
|
|
|
|
|
|
Также если используем свойство _TargetType_, то в значении атрибута _Property_ уже необязательно указывать тип, то есть `Property="Control.FontFamily"`. И в данном случае тип можно просто опустить: `Property="FontFamily"`
|
|
|
|
|
|
-Если же необходимо, чтобы к какой-то кнопке не применялся автоматический стиль, то ее стилю присваивают значение null
|
|
|
+Если же необходимо, чтобы к какой-то кнопке не применялся автоматический стиль, то ее стилю присваивают значение `null`
|
|
|
|
|
|
```xml
|
|
|
<Button
|
|
|
@@ -220,8 +209,8 @@ Hам необязательно прописывать для всех кноп
|
|
|
|
|
|
```xml
|
|
|
<Style
|
|
|
- TargetType="Button">
|
|
|
- ...
|
|
|
+ TargetType="Button"
|
|
|
+>
|
|
|
<EventSetter
|
|
|
Event="Button.Click"
|
|
|
Handler="Button_Click" />
|
|
|
@@ -244,8 +233,12 @@ private void Button_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
|
```xml
|
|
|
<Window.Resources>
|
|
|
- <Style x:Key="ButtonParentStyle">
|
|
|
- <Setter Property="Button.FontFamily" Value="Andy" />
|
|
|
+ <Style
|
|
|
+ x:Key="ButtonParentStyle"
|
|
|
+ >
|
|
|
+ <Setter
|
|
|
+ Property="Button.FontFamily"
|
|
|
+ Value="Andy" />
|
|
|
</Style>
|
|
|
<Style
|
|
|
x:Key="ButtonChildStyle"
|
|
|
@@ -264,9 +257,9 @@ Cвойство _BasedOn_ в качестве значения принимае
|
|
|
|
|
|
Если в дочернем стиле есть сеттеры для свойств, которые также используются в родительском стиле, как в данном случае сеттер для свойства _Button.FontFamily_, то дочерний стиль переопределяет родительский стиль.
|
|
|
|
|
|
-### Стили в C#
|
|
|
+### Стили в `C#`
|
|
|
|
|
|
-В `C#` стили представляют объект **System.Windows.Style**. Используя его, мы можем добавлять сеттеры и устанавливать стиль для нужных элементов:
|
|
|
+В **C#** стили представляют объект **System.Windows.Style**. Используя его, мы можем добавлять сеттеры и устанавливать стиль для нужных элементов:
|
|
|
|
|
|
|
|
|
```cs
|
|
|
@@ -423,7 +416,6 @@ new Setter {
|
|
|
|
|
|
Теперь применим эти стили. Для этого изменим файл `MainWindow.xaml.cs` следующим образом:
|
|
|
|
|
|
-
|
|
|
```cs
|
|
|
public partial class MainWindow : Window
|
|
|
{
|
|
|
@@ -459,7 +451,9 @@ public partial class MainWindow : Window
|
|
|
|
|
|
В итоге при выборе элемента в списке будет меняться применяемая к приложению тема.
|
|
|
|
|
|
-## Переключение вида списка
|
|
|
+## Переключение вида ListBox ("список" vs "плитка")
|
|
|
+
|
|
|
+>Два инициативных студента по итогам прошлой лекции решили сделать переключение вида отображения "список" и "плитка" кнопкой.
|
|
|
|
|
|
1. Переносим настройки **ListBox** в ресурсы окна (в том числе и шаблон элемента списка):
|
|
|
|
|
|
@@ -501,7 +495,7 @@ public partial class MainWindow : Window
|
|
|
<Image
|
|
|
Width="64"
|
|
|
Height="64"
|
|
|
- Source="{Binding ImageBitmap}"/>
|
|
|
+ Source="{Binding imageBitmap}"/>
|
|
|
|
|
|
<StackPanel
|
|
|
Grid.Column="1"
|
|
|
@@ -509,7 +503,7 @@ public partial class MainWindow : Window
|
|
|
Margin="5,2,0,5"
|
|
|
>
|
|
|
<TextBlock Text="{Binding name}"/>
|
|
|
- <TextBlock Text="{Binding surname}"/>
|
|
|
+ <TextBlock Text="{Binding breed.title}"/>
|
|
|
</StackPanel>
|
|
|
|
|
|
<TextBlock
|
|
|
@@ -554,12 +548,12 @@ public partial class MainWindow : Window
|
|
|
>
|
|
|
<Image
|
|
|
Width="200"
|
|
|
- Source="{Binding ImageBitmap}"/>
|
|
|
+ Source="{Binding imageBitmap}"/>
|
|
|
<TextBlock
|
|
|
Text="{Binding name}"
|
|
|
HorizontalAlignment="Center"/>
|
|
|
<TextBlock
|
|
|
- Text="{Binding surname}"
|
|
|
+ Text="{Binding breed.title}"
|
|
|
HorizontalAlignment="Center"/>
|
|
|
<TextBlock
|
|
|
Text="{Binding age}"
|
|
|
@@ -573,7 +567,7 @@ public partial class MainWindow : Window
|
|
|
</Window.Resources>
|
|
|
```
|
|
|
|
|
|
-2. **ListBox**-у задаем стиль по-умолчанию
|
|
|
+1. **ListBox**-у задаем стиль по-умолчанию
|
|
|
|
|
|
```xml
|
|
|
<ListBox
|
|
|
@@ -595,7 +589,7 @@ public partial class MainWindow : Window
|
|
|
</ListBox.ItemContainerStyle>
|
|
|
```
|
|
|
|
|
|
-3. В верхнюю панель (где у нас элементы управления для фильтраци, поиска и т.п.) добавляем кнопку "Сменить стиль" и в её обработчике переопределяем стиль для **ListBox**-а
|
|
|
+1. В верхнюю панель (где у нас элементы управления для фильтраци, поиска и т.п.) добавляем кнопку "Сменить стиль" и в её обработчике переопределяем стиль для **ListBox**-а
|
|
|
|
|
|
```cs
|
|
|
// храним текущий стиль
|