• WPF窗口继承实现统一风格的自定义窗口


    如何实现一个窗口的风格(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 >= 2)
                    {
                        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窗口继承

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

  • 相关阅读:
    .NET内存管理、垃圾回收
    C#容器类,性能介绍
    与LINQ有关的语言特性
    IMEI
    IMSI
    无源码调试smali
    IDA远程调试 在内存中dump Dex文件
    error C4996: 'scanf': This function or variable may be unsafe.
    vue 用axios实现调用接口下载excel
    读《JavaScript权威指南》笔记(三)--对象
  • 原文地址:https://www.cnblogs.com/DreamRecorder/p/9662081.html
Copyright © 2020-2023  润新知