日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

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

發布時間:2023/12/10 asp.net 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [WPF疑难] 继承自定义窗口 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[WPF疑難] 繼承自定義窗口

原文 [WPF疑難] 繼承自定義窗口

[WPF疑難] 繼承自定義窗口

周銀輝

項目中有不少的彈出窗口,按照美工的設計其外邊框(包括最大化,最小化,關閉等按鈕)自然不同于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,編譯順利通過,繼承成功。

挫敗2,外邊框(包括最小化,最大化和關閉按鈕)放在哪里

明顯,不能作為BaseWindow的內容,這是因為繼承了BaseWindow的子類窗口(比如Window1)會覆蓋BaseWindow的內容。

假設BaseWindow這樣編寫:

??????? public BaseWindow()

??????? {

??????????? Grid grid = new Grid();

??????????? Button minBtn = new Button();

??????????? Button maxBtn = new Button();

??????????? Button closeBtn =new Button();

??????????? //something to ini these buttons

??????????? grid.Children.Add(minBtn);

??????????? grid.Children.Add(maxBtn);

??????????? grid.Children.Add(closeBtn);

??????????? this.Content = grid;

??????? }

當子類Window1如下定義時:

<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>

??????? <TextBlock Text="hi , i am window1"/>

??? </Grid>

</src:BaseWindow>

這樣以來Window1中的Grid和TextBlock會覆蓋BaseWindow的內容而僅僅看到“hi,I am window1”的文本塊而沒有最小化最大化以及關閉按鈕了。

事實上,我們應該反過來想,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" />

??????? <!—Something else-->

??? </Style>

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

??????? private void InitializeStyle()

??????? {

??????????? this.Style = (Style) App.Current.Resources["BaseWindowStyle"];

??????? }

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

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

只有外觀還不夠,至少得有鼠標事件吧。那最小化事件來說,要做的事情是找到定義在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。

至此,問題搞定。下載DEMO:http://files.cnblogs.com/zhouyinhui/InheritWindowDemo.zip

posted on 2013-11-26 19:57 NET未來之路 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/lonelyxmas/p/3444011.html

總結

以上是生活随笔為你收集整理的[WPF疑难] 继承自定义窗口的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。