首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 自訂視窗繼承:ControlTemplate 統一標題列與按鈕邏輯

     編輯:關於.NET

繼承 Window 的兩大坑

  1. XAML 根元素衝突:子視窗 XAML 根標籤預設為 <Window>,改為基類 <src:BaseWindow> 時,若基類本身有 XAML 會報錯「無法作為 XAML 根元素」。解決:基類僅用 C# 定義,不提供 BaseWindow.xaml。
  2. 內容被覆蓋:基類建構子設定 this.Content,子視窗 XAML 內容會取代之。解決:將標題列、按鈕移入 ControlTemplate,內容由 ContentPresenter 呈現。

基類實作

ControlTemplate 定義標題列與三大按鈕

<ControlTemplate x:Key="BaseWindowTemplate" TargetType="{x:Type Window}">
  <DockPanel LastChildFill="True">
    <Border DockPanel.Dock="Top" Background="#FF7097D0" CornerRadius="4,4,0,0">
      <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
        <Button x:Name="BtnMin" Content="Min" />
        <Button x:Name="BtnMax" Content="Max" />
        <Button x:Name="BtnClose" Content="Close" />
      </StackPanel>
    </Border>
    <Border Background="{TemplateBinding Background}"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            CornerRadius="0,0,4,4">
      <AdornerDecorator><ContentPresenter /></AdornerDecorator>
    </Border>
  </DockPanel>
</ControlTemplate>

Style 套用 Template 與視窗屬性

<Style x:Key="BaseWindowStyle" TargetType="{x:Type Window}">
  <Setter Property="Template" Value="{StaticResource BaseWindowTemplate}" />
  <Setter Property="WindowStyle" Value="None" />
  <Setter Property="AllowsTransparency" Value="True" />
  <Setter Property="BorderBrush" Value="#FF7097D0" />
  <Setter Property="BorderThickness" Value="4,0,4,4" />
</Style>

基類建構子套用樣式並綁定按鈕事件

public class BaseWindow : Window
{
    public BaseWindow()
    {
        Loaded += (s, e) => InitializeChrome();
    }

    private void InitializeChrome()
    {
        var template = (ControlTemplate)Application.Current.Resources["BaseWindowTemplate"];
        var minBtn = (Button)template.FindName("BtnMin", this);
        var maxBtn = (Button)template.FindName("BtnMax", this);
        var closeBtn = (Button)template.FindName("BtnClose", this);

        minBtn.Click += (s, e) => WindowState = WindowState.Minimized;
        maxBtn.Click += (s, e) => WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
        closeBtn.Click += (s, e) => Close();
    }
}

關鍵:必須在 Loaded 後呼叫 FindName,此時 Template 已套用完成。

子視窗使用

<src:BaseWindow xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:src="clr-namespace:MyProject"
                x:Class="MyProject.ChildWindow"
                Style="{StaticResource BaseWindowStyle}">
    <Grid>
        <TextBlock Text="這是子視窗內容" />
    </Grid>
</src:BaseWindow>

所有彈出視窗統一外觀與行為,維護成本大幅降低。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved