Как создать пользовательский компонент на основе MaterialDesign?

#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 (на который вы ориентируетесь), вы можете повторно использовать такие свойства и определить свой собственный стиль.