一睹为快:
1.创建自定义控件,并取名为LayuiWPFStyle
2.在当前目录中创建Fonts和WindowStyle文件加用来存放字体文件和自定义窗体,字体用fontawesome字体当然你们可以用自己的自己也行
3.创建自定义控件,并取名为LayWindow,记住是WPF的别点错了
4.双击LayWindow让当前类文件继承Window
5.由于我们窗体分为头部和内容,而头部分为窗体名称和窗体图标以及窗体按钮组成
6.此时我们需要对窗体进行重绘以及添加必要的附加属性,快捷键Propdp+双击Tab,MyProperty是扩展属性名称我们可以随便定义,例如我们需要定义窗体头部栏高度我们可以定义为HearderHieght,类型为Int,ownerclass替换为当前自定义窗体的名称:LayWindow,
如图二
7.进入Generic.xaml文件中,我们会发现当我们每创建一个自定义控件时系统会默认帮我创建一个简单的Style样式,但是此时的样式时不奏效的,他只是给我们个友好的提示。此时我们需要开始从写窗体样式了,我们可以将窗体分为两份,一份为头部一分为身体(也就是内容)我们可以使用RowDefinitions进行分行,头部高度设置为自适应类容高度如图Height="auto"
8.创建一个头部栏:并且此时可以开始用上我们的自定义属性HearderHieght,切记我们自定义的属性想要生效不能用TemplateBinding(模板绑定)进行绑定必须要用Binding(数据源绑定)进行绑定如:Height="{Binding Path=HearderHieght, RelativeSource={RelativeSource Mode=TemplatedParent}}"
9.窗体内容我们用ContentPresenter进行组合使用
10.定制窗体头部,分别头部分为三列,左边分为窗体图标和窗体名称,中间预留,右边分为最大化、最小化和关闭按钮,为了方便我们统一颜色我将背景色单独抽离开
<Style TargetType="{x:Type local:LayWindow}" >
<Setter Property="Background" Value="{StaticResource WindowBackground}"/>
<Setter Property="HearderHieght" Value="35"/>
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="HearderFontColor" Value="White"/>
<Setter Property="Margin" Value="7"/>
<Setter Property="WindowChrome.WindowChrome" >
<Setter.Value>
<WindowChrome CaptionHeight="0" ResizeBorderThickness="10"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:LayWindow}">
<Border Padding="{TemplateBinding Margin}">
<Grid>
<Grid Background="#ccc" >
<Grid.Effect>
<DropShadowEffect ShadowDepth="0" Direction="0" BlurRadius="5" Color="#ccc">
</DropShadowEffect>
</Grid.Effect>
</Grid>
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border x:Name="WindowHearder" Height="{Binding Path=HearderHieght, RelativeSource={RelativeSource Mode=TemplatedParent}}" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"/><!--顶部颜色-->
<Grid x:Name="HearderContent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<Image Source="{TemplateBinding Icon}" VerticalAlignment="Center"/><!--窗体图标-->
<TextBlock Text="{TemplateBinding Title}" VerticalAlignment="Center" Foreground="{Binding Path=HearderFontColor,RelativeSource={RelativeSource Mode=TemplatedParent}}"/><!--窗体名称-->
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Column="2">
<!--最小化按钮-->
<Button Visibility="{Binding Path=WinMinBtnVisibility,RelativeSource={RelativeSource Mode=TemplatedParent}}" Content="" x:Name="WinMinBtn" Uid="1"
Style="{DynamicResource windowBtn}" Foreground="{TemplateBinding HearderFontColor}" Width="{Binding Path=HearderHieght, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Height="{Binding Path=HearderHieght, RelativeSource={RelativeSource Mode=TemplatedParent}}" ToolTip="{TemplateBinding ToolTip}" />
<!--最大化按钮-->
<Button Visibility="{Binding Path=WinMaxBtnVisibility,RelativeSource={RelativeSource Mode=TemplatedParent}}" Content="" x:Name="WinMaxBtn" Uid="2"
Style="{DynamicResource windowBtn}" Foreground="{TemplateBinding HearderFontColor}" Width="{Binding Path=HearderHieght, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Height="{Binding Path=HearderHieght, RelativeSource={RelativeSource Mode=TemplatedParent}}" ToolTip="{TemplateBinding ToolTip}"/>
<!--关闭按钮-->
<Button Content="" RenderTransformOrigin="0.5,0.5" x:Name="WinCloseBtn" Uid="3" Style="{DynamicResource windowBtn}" Foreground="{TemplateBinding HearderFontColor}"
Width="{Binding Path=HearderHieght, RelativeSource={RelativeSource Mode=TemplatedParent}}" Height="{Binding Path=HearderHieght, RelativeSource={RelativeSource Mode=TemplatedParent}}"
ToolTip="{TemplateBinding ToolTip}"/>
</StackPanel>
</Grid>
<ContentPresenter Grid.Row="1"/>
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="WinMinBtnVisibility" Value="False">
<Setter Property="Visibility" TargetName="WinMinBtn" Value="Collapsed"/>
</Trigger>
<Trigger Property="WinMaxBtnVisibility" Value="False">
<Setter Property="Visibility" TargetName="WinMaxBtn" Value="Collapsed"/>
</Trigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=Self},Path=WindowHearderVisibility}" Value="False">
<Setter Property="Visibility" TargetName="HearderContent" Value="Collapsed"/>
<Setter Property="Visibility" TargetName="WindowHearder" Value="Collapsed"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
11.此时我们的Style样式写完了开始实现功能,此时我们回到LayWindow.CS文件中,实现public override void OnApplyTemplate方法,此方法时方便我们查找我们模板中的某些控件如窗体按钮
public class LayWindow : Window
{
private Button WinMaxBtn;//全局最大化按钮
private bool WinMax = true;//全局最大窗体控制
static LayWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(LayWindow), new FrameworkPropertyMetadata(typeof(LayWindow)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
SizeChanged += new SizeChangedEventHandler(WindowSizeChanged);//实现窗体大小变化方法
Border WindowHearder = this.Template.FindName("WindowHearder",this) as Border;
WindowHearder.MouseLeftButtonDown += new MouseButtonEventHandler(WindowDisplacement);//注册窗体移动事件
Button WinMinBtn = this.Template.FindName("WinMinBtn", this) as Button;//查找最小化按钮
WinMinBtn.ToolTip = "最小化";//设置按钮提示名称
WinMinBtn.Click += new RoutedEventHandler(WinBtn_Click);//实现按钮点击方法
WinMaxBtn = this.Template.FindName("WinMaxBtn", this) as Button;//查找最大化按钮
WinMaxBtn.ToolTip = "最大化";//设置按钮提示名称
if (WinMaxBtn.Visibility != Visibility.Visible) WinMax = false;
WinMaxBtn.Click += new RoutedEventHandler(WinBtn_Click);//实现按钮点击方法
Button WinCloseBtn = this.Template.FindName("WinCloseBtn", this) as Button;//查找关闭按钮
WinCloseBtn.ToolTip = "关闭";//设置按钮提示名称
WinCloseBtn.Click += new RoutedEventHandler(WinBtn_Click);//实现按钮点击方法
}
/// <summary>
/// 窗体改变事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void WindowSizeChanged(object sender, SizeChangedEventArgs e)
{
Window window= sender as Window;
if (window.WindowState == WindowState.Maximized)
{
WinMaxBtn.Content = "\xf2d2";
}
else if(window.WindowState == WindowState.Normal)
{
WinMaxBtn.Content = "\xf2d0";
}
}
/// <summary>
/// 窗体按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void WinBtn_Click(object sender, RoutedEventArgs e)
{
WindowStyleChange(Convert.ToInt32((sender as Button).Uid), (sender as Button).TemplatedParent as Window);
}
/// <summary>
/// 窗体状态变化
/// </summary>
/// <param name="styleCode"></param>
/// <param name="window"></param>
private void WindowStyleChange(int styleCode ,Window window) {
switch (styleCode)
{
case 1:
window.WindowState = WindowState.Minimized;
break;
case 2:
if (window.WindowState == WindowState.Maximized)
{
WinMaxBtn.Content = "\xf2d0";
WinMaxBtn.ToolTip = "最大化";
window.WindowState = WindowState.Normal;
}
else
{
WinMaxBtn.Content = "\xf2d2";
WinMaxBtn.ToolTip = "还原";
window.WindowState = WindowState.Maximized;
}
break;
case 3:
window.Close();
break;
}
}
/// <summary>
/// 窗体移动事件
/// </summary>
/// <param name="sender">窗体头部</param>
/// <param name="e"></param>
private void WindowDisplacement(object sender, MouseButtonEventArgs e)
{
if ((sender as Border).TemplatedParent is Window) {
Window window = (sender as Border).TemplatedParent as Window;
switch (e.ClickCount)
{
case 1://左键单击效果
window.DragMove();
break;
case 2://左键双击效果
if(WinMax)
if (window.WindowState == WindowState.Maximized)
{
WinMaxBtn.Content = "\xf2d0";
window.WindowState = WindowState.Normal;
}
else
{
WinMaxBtn.Content = "\xf2d2";
window.WindowState = WindowState.Maximized;
}
break;
}
}
}
/// <summary>
/// 窗体头部高度
/// </summary>
public int HearderHieght
{
get { return (int)GetValue(HearderHieghtProperty); }
set { SetValue(HearderHieghtProperty, value); }
}
// Using a DependencyProperty as the backing store for HearderHieght. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HearderHieghtProperty =
DependencyProperty.Register("HearderHieght", typeof(int), typeof(LayWindow));
/// <summary>
/// 窗体头部字体样式
/// </summary>
public Brush HearderFontColor
{
get { return (Brush)GetValue(HearderFontColorProperty); }
set { SetValue(HearderFontColorProperty, value); }
}
// Using a DependencyProperty as the backing store for HearderFontColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HearderFontColorProperty =
DependencyProperty.Register("HearderFontColor", typeof(Brush), typeof(LayWindow));
/// <summary>
/// 窗体头部栏状态
/// </summary>
public bool WindowHearderVisibility
{
get { return (bool)GetValue(WindowHearderVisibilityProperty); }
set { SetValue(WindowHearderVisibilityProperty, value); }
}
// Using a DependencyProperty as the backing store for WindowHearderVisibility. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WindowHearderVisibilityProperty =
DependencyProperty.Register("WindowHearderVisibility", typeof(bool), typeof(LayWindow), new PropertyMetadata(true));
#region 窗体头部栏控制
public bool WinMinBtnVisibility
{
get { return (bool)GetValue(WinMinBtnVisibilityProperty); }
set { SetValue(WinMinBtnVisibilityProperty, value); }
}
// Using a DependencyProperty as the backing store for WinMinBtnVisibility. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WinMinBtnVisibilityProperty =
DependencyProperty.Register("WinMinBtnVisibility", typeof(bool), typeof(LayWindow), new PropertyMetadata(true));
public bool WinMaxBtnVisibility
{
get { return (bool)GetValue(WinMaxBtnVisibilityProperty); }
set { SetValue(WinMaxBtnVisibilityProperty, value); }
}
// Using a DependencyProperty as the backing store for WinMinBtnVisibility. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WinMaxBtnVisibilityProperty =
DependencyProperty.Register("WinMaxBtnVisibility", typeof(bool), typeof(LayWindow), new PropertyMetadata(true));
#endregion
}
<FontFamily x:Key="FontFamilyStyle">/LayuiWPFStyle;component/Fonts/#FontAwesome</FontFamily>
<Style TargetType="TextBlock" >
<Setter Property="FontFamily" Value="{StaticResource FontFamilyStyle}"/>
<Setter Property="FontSize" Value="16"/>
</Style>
<Style x:Key="btnBase" TargetType="Button" >
<Setter Property="Cursor" Value="Hand"/>
</Style>
<Style x:Key="windowBtn" TargetType="Button" BasedOn="{StaticResource btnBase}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border x:Name="WindowHearder" Height="{Binding Path=HearderHieght, RelativeSource={RelativeSource Mode=TemplatedParent}}" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
12,此时我们的自定义窗体的所有业务代码已完成,创建一个WPF项目,我们取名为Layui-WPFUI,并且引用我们刚刚做好的窗体
13.窗机WPF项目中的App.xaml文件添加自定义控件的相关样式文件
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/LayuiWPFStyle;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
14.点击MainWindow将原来的左上角的Window替换为Lay:LayWindow,并且引用xmlns:Lay="clr-namespace:LayuiWPFStyle;assembly=LayuiWPFStyle"如图
16.按F7进入后台代码让MainWindow继承我们的LayWindow
17.此时我们的自定义窗体就完成啦,点击运行就得到我们的美化后的窗体(顶部左侧的Ico图标可忽略自己也可以添加一个Ico图标)
注意:如若你的项目运行出错很有可能你的Generic.xaml文件里面有文字注释,上图中我是为了方便学习特意添加注释,当控件写完后可将注释去掉即可
来源:oschina
链接:https://my.oschina.net/u/4297638/blog/4283497