#wpf #xaml #material-design #material-design-in-xaml
Вопрос:
Я пытаюсь понять, как создать пользовательский компонент на основе дизайна материалов, чтобы понять , как именно работает процедура для достижения этой цели, я подумал о создании простой кнопки, включающей текст и значок (помните, это просто для упражнения), поэтому я попытался написать и а UserControl
, и а ResurceDictionary
, но пока безуспешно. Мой вопрос в том, как я могу создать пользовательскую кнопку на основе дизайна материалов? Я хочу, чтобы он сохранял все эффекты и тени, поставляемые с material design. Я также опубликую то, что у меня есть с точки зрения ResurceDictionary
.
РесурсосБерегающий
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:KESS3Mockup">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type local:VerticalButton}" BasedOn="{StaticResource ResourceKey={x:Type Button}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:VerticalButton}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="2"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.5*"/>
<RowDefinition Height="8*"/>
<RowDefinition Height="8*"/>
<RowDefinition Height="0.5*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Viewbox HorizontalAlignment="Stretch" Grid.Column="1" Grid.Row="1">
<materialDesign:PackIcon Kind="{TemplateBinding Kind}" Foreground="White" />
</Viewbox>
<Viewbox Grid.Column="1" Grid.Row="2">
<TextBox Text="{TemplateBinding Text}" Foreground="White" SelectionBrush="#000078D7" BorderBrush="#00000000" Focusable="False"/>
</Viewbox>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Комментарии:
1. Основывайте стиль вашего пользовательского элемента управления на стилях дизайна материалов? Или в чем именно заключается ваш вопрос?
2. @mm8 да, это моя цель
Ответ №1:
Вы можете создать новый стиль на основе существующего стиля с помощью BasedOn
.
<Style TargetType="{x:Type local:VerticalButton}" BasedOn="{StaticResource {x:Type Button}}">
Вместо типа вы также можете ссылаться на другой, определенный стиль.
<Style TargetType="{x:Type local:VerticalButton}" BasedOn="{StaticResource MaterialDesignFlatButton}"/>
Однако для того, чтобы это работало, целевые типы должны быть совместимы (либо одного типа, либо базового типа, например ButtonBase
, для a Button
). Вы не можете просто создать a UserControl
и создать стиль, основанный на стиле для a Button
. Чтобы настроить a Button
, вам нужно будет создать пользовательский элемент управления , VerticalButton
который наследуется от Button
, который реализует нужные вам свойства зависимостей и особенности.
public class VerticalButton : Button
{
static VerticalButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(VerticalButton), new FrameworkPropertyMetadata(typeof(VerticalButton)));
}
// ...your custom code.
}
Затем вы создадите Generic.xaml
файл в Themes
папке своего проекта (этот путь и файл названы по соглашению). Там вы определяете стиль по умолчанию, который может быть основан на дизайне материалов.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:YourProject">
<Style TargetType="{x:Type local:VerticalButton}" BasedOn="{StaticResource {x:Type Button}}">
<!-- ...your style definitions. -->
</Style>
</ResourceDictionary>
Этот раздел ресурсов должен быть включен после словарей тем Material Design App.xaml
. Для получения дополнительной информации о том, как переопределить темы дизайна материалов по умолчанию, вы можете обратиться к Вики.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Пожалуйста, не забывайте, что, хотя вы можете основывать стиль на другом стиле, вы не можете основывать один шаблон элемента управления на другом. Это означает, что если вы назначите a ControlTemplate
в своем стиле, он переопределит один из базовых стилей. Поэтому, если вы хотите адаптировать шаблон элемента управления, сохранив большую часть его визуальных элементов и эффектов по умолчанию, вам необходимо скопировать его из репозитория Material Design GitHub и адаптировать к вашим потребностям.
Дополнительные сведения о разработке пользовательских элементов управления в целом см. в разделе Обзор создания элементов управления. Material Design использует установленные концепции для тем, стилей и шаблонов, поэтому на самом деле он не отличается от стандартных элементов управления WPF или создания пользовательских элементов управления.
Для простых случаев настройки содержимого кнопки может быть проще создать альтернативу DataTemplate
, которую вы назначаете в качестве ContentTemplate
Button
, см. Обзор шаблонов данных.
Ответ №2:
Когда вы устанавливаете шаблон элемента управления, он переопределяет все визуальные стили. Он просто несет в себе только свойства зависимости. Таким образом, он не будет нести никаких теневых или других эффектов (по крайней мере, в вашем новом стиле). однако, если такое свойство существует в классе VerticalButton (на который вы ориентируетесь), вы можете повторно использовать такие свойства и определить свой собственный стиль.