項目中有不少的快顯視窗,按照美工的設計其外邊框(包括最大化,最小化,關閉等按鈕)自然不同於Window自身的,但每個彈出框的外邊框都是一樣的。對其中一個視窗而言,我們要取消其Window邊框,並在右上方擺上三個按鈕並編寫其點擊事件等,但若每個快顯視窗都按照這種方式做一遍就太土了。我們想避免重複勞動,最自然的聯想到了“繼承”。但WPF給我們找了若干麻煩,被挫敗了幾次。今天經過2小時的奮戰,終於搞定了,分享一下。
挫敗1,繼承時編譯錯誤
假設我們寫好的父視窗類為BaseWindow,對應BaseWindow.cs和BaseWindow.xaml, 要繼承它的視窗為Window1,對應Window1.cs和Window1.xaml,我們常常進行的動作是將VS為我們自動產生的程式碼中的如下語句:
public partial class Window1 : Window
修改成:
public partial class Window1 : BaseWindow
但編譯後,你會得到一個錯誤:Window1有著不同的基類。
這是因為在window1.xaml中
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="InheritWindowDemo.Window1" Width="300" Height="300"> <Grid x:Name="LayoutRoot"/></Window>
我們的Window繼承了Window類,開啟Window1.g.cs也可以看到這一點(這是VS自動產生的一個中間檔案,可以在Window1的InitializeComponent()方法上“轉到定義”來跳轉到該檔案,也可以在Obj"Debug目錄下找到)。這就使得我們的Window1同時繼承Window和BaseWindow類,多繼承是不被允許的。
那麼自然地,需要修改Window1.xaml,將其中的根“Window”,修改成我們的BaseWindow:
<src: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></src:BaseWindow>
心想,這下可以編譯通過了吧,抱歉,不行,又得到另一個編譯錯誤:src:BaseWindow不能是Xaml檔案的根,因為它是由Xaml定義的,目前我避免這個問題的辦法是讓BaseWindow僅僅在C#中定義(即,沒有BaseWindow.xaml,只有BaseWindow.cs)。
OK,編譯順利通過,繼承成功。