WPF 之 創建繼承自Window 基類的自定義窗口基類


  開發項目時,按照美工的設計其外邊框(包括最大化,最小化,關閉等按鈕)自然不同於 Window 自身的,但窗口的外邊框及窗口移動、最小化等標題欄操作基本都是一樣的。所以通過查看資料,可按如下方法創建繼承自 Window 基類的自定義窗口基類。

一、窗口基類的創建

  添加一個名為 BaseWindow 的 C# 的后台類,Window 類在 System.Windows 命名空間下。像關閉事件,雙擊事件、最大化與還原事件可能存在重載版本的時間及方法需要用 virtual 關鍵字標識。

using System;
using System.Windows;
using System.Windows.Input;

namespace Client.AppCode
{
    public partial class BaseWindow:Window
    {
        #region 窗口事件函數

        /// <summary>
        /// 窗口移動事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void TitleBar_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                this.DragMove();
            }
        }

        /// <summary>
        /// 窗口最大化與還原
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void btn_max_Click(object sender, RoutedEventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
            {
                this.WindowState = WindowState.Normal; //設置窗口還原
            }
            else
            {
                this.WindowState = WindowState.Maximized; //設置窗口最大化
            }
        }
        
        /// <summary>
        /// 窗口最小化事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btn_min_Click(object sender, RoutedEventArgs e)
        {
            this.WindowState = WindowState.Minimized; //設置窗口最小化
        }

        /// <summary>
        /// 關閉窗口事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void btn_close_Click(object sender, RoutedEventArgs e)
        {
            this.Close(); //關閉窗口
        }
        
        int i = 0;
        /// <summary>
        /// 雙擊事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void dpTitle_MouseDown(object sender, MouseButtonEventArgs e)
        {
            //如果是右鍵點擊,直接返回
            if (e.RightButton == MouseButtonState.Pressed)
                return;

            i += 1;
            System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
            timer.Interval = new TimeSpan(0, 0, 0, 0, 300);
            timer.Tick += (s, e1) => { timer.IsEnabled = false; i = 0; };
            timer.IsEnabled = true;

            //如果不是雙擊,直接返回
            if (i % 2 != 0)
                return;

            timer.IsEnabled = false;
            i = 0;
            this.WindowState = this.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
        }

        #endregion 窗口事件函數
    }
}

二、具體使用

1、新建窗體繼承自自定義窗體基類。

  創建窗口類,后台類改為繼承自定義的 窗體基類。

public partial class Window1 : BaseWindow

  對應的前台的 .xaml 文件中,需要修改 Window1.xaml,將其中的根“Window”,修改成我們的BaseWindow:

<custom:BaseWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="InheritWindowDemo.Window1"
    xmlns:src="clr-namespace:InheritWindowDemo"
    Height="300" Width="300">
    <Grid></Grid>
</custom:BaseWindow>

2、自定義窗體邊框及標題欄事件

  事實上,我們反過來想,Window也是一個控件,與其他控件一樣其外觀及其外觀中的視覺元素仍然是由其Style和ControlTemplate來定義的。所以,應該將窗口外邊框(包括最小化,最大化和關閉按鈕)定義在其Template中,其他一些屬性(比如是否支持透明等)定義在Style中

  其Template如下:

<ControlTemplate x:Key="BaseWindowControlTemplate" TargetType="{x:Type Window}">
        <DockPanel LastChildFill="True">
            <!--外邊框-->
            <Border Width="Auto" Height="Auto" DockPanel.Dock="Top"
                    Background="#FF7097D0" CornerRadius="4,4,0,0" x:Name="borderTitle">
                <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
                    <!--最小化按鈕-->
                    <Button Content="Min" x:Name="btnMin" />
                    <!--最大化按鈕-->
                    <Button Content="Max" x:Name="btnMax" />
                    <!--關閉按鈕-->
                    <Button Content="Close" x:Name="btnClose" />
                </StackPanel>
            </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如下:

<Style x:Key="BaseWindowStyle" TargetType="{x:Type Window}">  
  <
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,0,4,4" />
</Style>

  然后在BaseWindow的構造函數中指定其Style為我們定義的樣式:

private void InitializeStyle()
{
    this.Style = (Style) App.Current.Resources["BaseWindowStyle"];
}

  所有繼承了BaseWindow的窗體,都有我們統一定義的外觀了。

  讓外邊框(包括最小化,最大化和關閉按鈕)響應事件

  拿最小化事件來說,要做的事情是找到定義在ControlTemplate中的btnMin這個Button控件,然后當其被點擊時該ControlTemplate被應用到的那個窗體被最小化。

  FrameworkTemplate.FindName(string name, FrameworkElement templatedParent)方法可以做幫助我們找到指定的FrameworkTemplate被應用到templatedParent上后具有name名稱的控件。

ControlTemplate baseWindowTemplate = (ControlTemplate)App.Current.Resources["BaseWindowControlTemplate"];
Button minBtn = (Button)baseWindowTemplate.FindName("btnMin", this);
minBtn.Click += delegate
{
    this.WindowState = WindowState.Minimized;
};

  其他事件同理:注意,上面這樣的代碼應該在窗體的Style和Template被應用之后,比如你可以在Loaded后編寫使用上面的代碼而不是直接放在構造方法中,否則FrameworkTemplate.FindName()方法將返回null。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM