如何基于 MaterialDesign 构建自定义组件?
Posted
技术标签:
【中文标题】如何基于 MaterialDesign 构建自定义组件?【英文标题】:How to build a custom component based on MaterialDesign? 【发布时间】:2021-05-31 18:27:11 【问题描述】:我正在尝试了解如何基于材料设计构建自定义组件,以了解实现该过程的确切过程是如何工作的,我想构建一个包含文本和图标的简单按钮(记住只是用于锻炼),所以我尝试同时编写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>
【问题讨论】:
将自定义控件的样式基于 Material Design 样式?或者你的问题到底是什么? @mm8 是的,这就是我的目标 【参考方案1】:您可以使用 BasedOn
在现有样式的基础上创建新样式。
<Style TargetType="x:Type local:VerticalButton" BasedOn="StaticResource x:Type Button">
除了类型,您还可以引用不同的特定样式。
<Style TargetType="x:Type local:VerticalButton" BasedOn="StaticResource MaterialDesignFlatButton"/>
但是,要使其工作,目标类型必须兼容(相同类型或基本类型,例如 ButtonBase
用于 Button
)。您不能简单地创建UserControl
并基于Button
的样式创建样式。为了自定义Button
,您必须创建一个继承自Button
的自定义控件VerticalButton
,它实现了您想要的依赖属性和细节。
public class VerticalButton : Button
static VerticalButton()
DefaultStyleKeyProperty.OverrideMetadata(typeof(VerticalButton), new FrameworkPropertyMetadata(typeof(VerticalButton)));
// ...your custom code.
接下来,您将在项目的Themes
文件夹中创建一个Generic.xaml
文件(此路径和文件按约定命名)。您可以在此处定义默认样式,该样式可以基于 Material Design。
<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>
此资源词典必须包含在 App.xaml
中的 Material Design 主题词典之后。有关如何覆盖默认 Material Design 主题的更多信息,您可以refer to the Wiki。
<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>
请注意,尽管您可以将一种样式基于另一种样式,但您不能基于另一种控件模板。这意味着,如果您在样式中指定 ControlTemplate
,它将覆盖基本样式之一。因此,如果您想调整控件模板,同时保留其大部分默认视觉效果和效果,您必须copy it from the Material Design GitHub repository 并根据您的需要进行调整。
有关开发自定义控件的更多信息,请参阅Control authoring overview。 Material Design 使用已建立的主题、样式和模板概念,因此它与标准 WPF 控件的样式或构建自定义控件没有真正的区别。
对于自定义按钮内容的简单案例,创建一个DataTemplate
并指定为Button
的ContentTemplate
可能是一种更简单的替代方法,请参阅Data Templating Overview。
【讨论】:
【参考方案2】:当您设置控件模板时,它会覆盖所有视觉样式。它仅带有依赖属性。因此,它不会带有任何阴影或其他效果(至少对您的新风格而言)。但是,如果此类属性存在于 VerticalButton 类(您的目标)中,那么您可以重用此类属性并定义您自己的样式。
【讨论】:
以上是关于如何基于 MaterialDesign 构建自定义组件?的主要内容,如果未能解决你的问题,请参考以下文章
如何自定义构建基于 Jquery 的 javascript API 以及关于 Jquery 中使用的语法的一些问题
Material Design系列,自定义Behavior支持所有View
Material Design系列,自定义Behavior之上滑显示返回顶部按钮