如何实现一个窗口的风格(style),让所有的窗口都继承这样同样的风格,包括标题栏,放大、缩小和关闭按钮。

那么,我们可不可以就建立一个Base窗口,然后将这个窗口的风格给设计好之后,所有的窗口都继承自他呢?

答案是否定的,我们一定要知道,窗口是一个类,它可以继承,但是风格(XAML)文件是继承不了的。

所以我们能够做到的是:

1、窗口类继承,BaseWindow封装窗口最大化按钮,最小化按钮的点击等事件。

2、风格(Style)就利用属性来设置,把window看成一个控件,利用Style=“BaseWindowStyle”就可以了。

以下是详细的步骤:

1、新建一个BaseWindowStyle的模板文件。点击项目名称,右键“添加”->”资源字典”->输入名称为“BaseWindowStyle.xaml”,然后将以下的末班文件拷贝进去:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ControlTemplate x:Key="WindowTemplateKey"
TargetType="{x:Type Window}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
<ResizeGrip Visibility="Collapsed"
IsTabStop="false"
HorizontalAlignment="Right"
x:Name="WindowResizeGrip"
VerticalAlignment="Bottom" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ResizeMode"
Value="CanResizeWithGrip" />
<Condition Property="WindowState"
Value="Normal" />
</MultiTrigger.Conditions>
<Setter Property="Visibility"
TargetName="WindowResizeGrip"
Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="BaseWindowControlTemplate" TargetType="{x:Type Window}">
<DockPanel LastChildFill="True">
<!--外边框-->
<Border Width="Auto"
Height="Auto"
DockPanel.Dock="Top"
Background="#FF7097D0"
CornerRadius="0,0,0,0"
x:Name="borderTitle"> <Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"> </ColumnDefinition>
<ColumnDefinition Width="*"> </ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Margin="20,0,2,2" Name="Title" VerticalAlignment="Top" FontSize="20"
Foreground="White" Text="{TemplateBinding Title}"/>
<StackPanel Grid.Column="1" HorizontalAlignment="Right"
Orientation="Horizontal"> <!--最小化按钮-->
<Button x:Name="btnMin" Content="M" Margin="2,2,2,2" Style="{DynamicResource MinButtonStyle}"/> <!--最大化按钮-->
<Button x:Name="btnMax" Content="M" Margin="2,2,2,2" Style="{DynamicResource MaxButtonStyle}"/>
<!--关闭按钮-->
<Button x:Name="btnClose" Content="M" Margin="2,2,2,2" Style="{DynamicResource CloseButtonStyle}"/>
</StackPanel>
</Grid> </Border>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Width="Auto"
Height="Auto"
DockPanel.Dock="Top"
CornerRadius="0,0,4,4">
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
</Border>
</DockPanel>
</ControlTemplate>
<Style x:Key="BaseWindowStyle"
TargetType="{x:Type Window}">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="Template" Value="{StaticResource BaseWindowControlTemplate}"/> <Setter Property="AllowsTransparency"
Value="True" />
<Setter Property="WindowStyle"
Value="None" />
<Setter Property="BorderBrush"
Value="#FF7097D0" />
<Setter Property="BorderThickness"
Value="4,4,4,4" />
<Style.Triggers>
<Trigger Property="ResizeMode"
Value="CanResizeWithGrip">
<Setter Property="Template"
Value="{StaticResource WindowTemplateKey}" />
</Trigger>
</Style.Triggers>
</Style>
<!--最小化按钮-->
<Style x:Key="MinButtonStyle" TargetType="{x:Type Button}"> <Setter Property="Foreground" Value="Black"/>
<!--修改模板属性-->
<Setter Property="Template">
<Setter.Value>
<!--控件模板-->
<ControlTemplate TargetType="Button">
<!--背景色-->
<Border x:Name="back" Opacity="0.8" CornerRadius="0" BorderBrush="#FFCDA05F" Background="#FFFFE9C9" BorderThickness="1" Margin="1" Padding="2,0,0,0">
<!--按钮内容-->
<Path x:Name="cp" Width="12" Height="12"
Stroke="#FFCEA15F"
StrokeThickness="3" Fill="Black"> <Path.Data>
<PathGeometry Figures="M 0,6 H 6,6 " />
</Path.Data>
</Path>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" TargetName="back" Value="#FFD4BD9B"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="back" Value="#FFCDA05F"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--最大化按钮-->
<Style x:Key="MaxButtonStyle" TargetType="{x:Type Button}"> <Setter Property="Foreground" Value="Black"/>
<!--修改模板属性-->
<Setter Property="Template">
<Setter.Value>
<!--控件模板-->
<ControlTemplate TargetType="Button">
<!--背景色-->
<Border x:Name="back" Opacity="0.8" CornerRadius="0" BorderBrush="#FFCDA05F" Background="#FFFFE9C9" BorderThickness="1" Margin="1" Padding="2,0,0,0">
<!--按钮内容-->
<Path x:Name="cp" Width="12" Height="12"
Stroke="#FFCEA15F"
StrokeThickness="3" > <Path.Data>
<PathGeometry Figures="M 0,0 L 0,12 12,12 12,0 0,0" />
</Path.Data>
</Path>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" TargetName="back" Value="#FFD4BD9B"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="back" Value="#FFCDA05F"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--关闭按钮-->
<Style x:Key="CloseButtonStyle" TargetType="{x:Type Button}"> <Setter Property="Foreground" Value="Black"/>
<!--修改模板属性-->
<Setter Property="Template">
<Setter.Value>
<!--控件模板-->
<ControlTemplate TargetType="Button">
<!--背景色-->
<Border x:Name="back" Opacity="0.8" CornerRadius="0" BorderBrush="#FFCDA05F" Background="#FFFFE9C9" BorderThickness="1" Margin="1" Padding="2,0,0,0">
<!--按钮内容-->
<Path x:Name="cp" Width="12" Height="12"
Stroke="#FFCEA15F"
StrokeThickness="3" > <Path.Data>
<PathGeometry Figures="M 0,0 L 12,12 M 0,12 L 12,0" />
</Path.Data>
</Path>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" TargetName="back" Value="#FFD4BD9B"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="back" Value="#FFCDA05F"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> </ResourceDictionary>

2、引用该模板文件。资源文件建立后,我们需要在程序中引用这个文件,打开APP.XAML,将引用的BaseWindowStyle添加进去:

<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="MyFirst.App"
StartupUri="MainWindow.xaml">
<Application.Resources> <ResourceDictionary Source="BaseWindowStyle.xaml"> </ResourceDictionary> </Application.Resources>
</Application>

3、建立BaseWindow类,实现窗口点击,拖动等事件。在工程上点击右键“添加”->“类”->输入”BaseWindow.cs“

该类继承自Window,然后要载入模板文件,在模板文件中获取最小化、最大化等按钮,然后将这些按钮的点击事件和窗口绑定起来,实现窗口的响应:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input; namespace MyFirst
{
public class BaseWindow : Window
{
public BaseWindow()
{
InitializeStyle();
this.Loaded += delegate
{
InitializeEvent();
};
} private void InitializeEvent()
{
ControlTemplate baseWindowTemplate = (ControlTemplate)App.Current.Resources["BaseWindowControlTemplate"]; Button minBtn = (Button)baseWindowTemplate.FindName("btnMin", this);
minBtn.Click += delegate
{ this.WindowState = WindowState.Minimized;
}; Button maxBtn = (Button)baseWindowTemplate.FindName("btnMax", this);
maxBtn.Click += delegate
{ this.WindowState = (this.WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal);
}; Button closeBtn = (Button)baseWindowTemplate.FindName("btnClose", this);
closeBtn.Click += delegate
{
this.Close();
}; Border borderTitle = (Border)baseWindowTemplate.FindName("borderTitle", this);
borderTitle.MouseMove += delegate(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
this.DragMove();
}
};
borderTitle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount >= )
{
maxBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
};
} private void InitializeStyle()
{
this.Style = (Style)App.Current.Resources["BaseWindowStyle"];
}
}
}

4,其它窗口类继承自BaseWindow:

public partial class MainWindow : BaseWindow

5,其它窗口的风格指向BaseWindowStyle。

这里要注意一点Winodow的风格可不是直接 Style=”BaseWindowStyle” 那么简单,可以看看MainWindow.xaml的代码:

<local:BaseWindow x:Class="MyFirst.Login"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:MyFirst"
Title="MainWindow" Height="300" Width="300"> </local:BaseWindow>

经过这么多步,我们终于实现了凡是继承自BaseWindow的窗口,都有统一的风格了!

当然,如上的窗口还不是那么漂亮完美,但是相信你有办法把它做的美美的!

WPF窗口继承实现统一风格的自定义窗口的更多相关文章

  1. WPF 实现完全可控制的漂亮自定义窗口

    在WPF界面开发中,有时候不想用系统的死板的窗口,想要来点新花样,常会自定义窗口. 那么,先抛出问题,想搞出下面这样的窗口,该咋整 ? aa  下面看一个啥也没设置过的普通窗口,这样的窗口,我们只能控 ...

  2. WPF.UIShell UIFramework之自定义窗口的深度技术 - 模态闪动(Blink)、窗口四边拖拽支持(WmNCHitTest)、自定义最大化位置和大小(WmGetMinMaxInfo)

    无论是在工作和学习中使用WPF时,我们通常都会接触到CustomControl,今天我们就CustomWindow之后的一些边角技术进行探讨和剖析. 窗口(对话框)模态闪动(Blink) 自定义窗口的 ...

  3. Kivy 中文教程 实例入门 简易画板 (Simple Paint App):1. 自定义窗口部件 (widget)

    1. 框架代码 用 PyCharm 新建一个名为 SimplePaintApp 的项目,然后新建一个名为 simple_paint_app.py 的 Python 源文件, 在代码编辑器中,输入以下框 ...

  4. unity编辑器扩展_08(创建自定义窗口)

    代码: using UnityEngine;using UnityEditor; public class MyWidow : EditorWindow{    [MenuItem("Win ...

  5. [WPF疑难] 继承自定义窗口

    原文 [WPF疑难] 继承自定义窗口 [WPF疑难] 继承自定义窗口 周银辉 项目中有不少的弹出窗口,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于Window自身的,但每个弹出框 ...

  6. WPF 之 创建继承自Window 基类的自定义窗口基类

    开发项目时,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于 Window 自身的,但窗口的外边框及窗口移动.最小化等标题栏操作基本都是一样的.所以通过查看资料,可按如下方法创建继承 ...

  7. WPF自定义窗口基类

    WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...

  8. WPF自学入门(九)WPF自定义窗口基类

    今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ...

  9. WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)

    WPF 自定义窗口样式有多种方式,不过基本核心实现都是在修改 Win32 窗口样式.然而,Windows 上的应用就应该有 Windows 应用的样子嘛,在保证自定义的同时也能与其他窗口样式保持一致当 ...

随机推荐

  1. MySql基本的语法(学习笔记)

    MySQL语法大全_自己整理的学习笔记 select * from emp;  #凝视 #--------------------------- #----命令行连接MySql--------- #启 ...

  2. vuex概念总结及简单使用实例

    原文 简书原文:https://www.jianshu.com/p/0546983f5997 大纲 1.什么是Vuex 2.什么是“状态管理模式”? 3.什么情况下应该使用 Vuex? 4.Vuex和 ...

  3. 【习题 3-4 UVA - 455】Periodic Strings

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举 [代码] #include <bits/stdc++.h> using namespace std; const ...

  4. License控制实现原理(20140808)

    近期须要做一个License控制的实现,做了一个设计,设计图例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGVjX2Zlbmc=/font/5 ...

  5. Xposed也要热更新

    好久没写博客了.这次玩一点不一样的. 吐槽&起因 相信熟悉Xposed的小伙伴们都知道,每次写完Xposed都要重新启动啊.有木有!反射错了,写错了名字.改一个log,都要重新启动啊有木有!重 ...

  6. JobService和JobScheduler机制在Android5.0以上保活

    JobService和JobScheduler机制在Android5.0以上保活 我们知道在Android5.0之前,Android源代码还是有不小漏洞的,导致非常多不光明的手段来进行++保活++.但 ...

  7. php求和为s的两个数字(多复制上面写的代码,有利于检查错误)(由浅入深,先写简单算法,做题的话够用就行)

    php求和为s的两个数字(多复制上面写的代码,有利于检查错误)(由浅入深,先写简单算法,做题的话够用就行) 一.总结 1.多复制上面写的代码,有利于检查错误 2.一层循环就解决了,前后两个指针,和大了 ...

  8. [Node.js] Take Screenshots of Multiple Dimensions for Responsive Sites using Nightmare

    When developing responsive websites, you will constantly be resizing your browser to make sure your ...

  9. IE浏览器下css hack

    \9    :所有IE浏览器都支持 _和-  :仅IE6支持 *     :IE6.IE7支持 \0    :IE8.IE9支持 \9\0  :IE8部分支持.IE9支持 \0\9  :IE8.IE9 ...

  10. SQLite单表4亿订单,大数据测试

    [转载] SQLite单表4亿订单,大数据测试 http://www.cnblogs.com/nnhy/p/BigData.html