c#學(xué)習(xí)之30分鐘學(xué)會XAML
1.狂妄的WPF
相對傳統(tǒng)的Windows圖形編程,需要做很多復(fù)雜的工作,引用許多不同的API。例如:WinForm(帶控件表單)、GDI+(2D圖形)、DirectX API(3D圖形)以及流媒體和流文檔等,都需要不同的API來構(gòu)建應(yīng)用程序。
WPF就是看著上面的操作復(fù)雜和不爽,自己決定做老大,想用DirectX技術(shù)涵蓋一切,于是想要將上述的東西全部融合到自身,減少復(fù)雜度,讓編程變得爽起來的技術(shù)。
而不可否認的是,WPF雖然很狂妄,但是這種技術(shù)里面還是有不少的可圈可點的東西。而支持WPF狂妄的資本,則就是和它后臺代碼可以前后分離的XAML技術(shù)。下面用30分鐘時間說一下XAML。
2.什么是XAML
一個界面程序的核心,無疑就是界面和后臺代碼,而xaml就是微軟為構(gòu)建應(yīng)用程序界面而創(chuàng)建的一種描述性語言,也就是說,這東西是搞界面的。
先上一段xaml代碼:
<Window x:Class='MyXaml.Window1' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' Title='MyXaml' Height='150' Width='300' > <Grid> <Grid.RowDefinitions> <RowDefinition Height='30'/> <RowDefinition Height='30'/> <RowDefinition Height='30'/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width='Auto'/> <ColumnDefinition Width='*'/> </Grid.ColumnDefinitions> <TextBlock Grid.Column='0' Grid.Row='0' FontWeight='Bold' Text='姓名:' Width='30'/> <TextBlock Grid.Column='0' Grid.Row='1' FontWeight='Bold' Width='30'>性別:</TextBlock> <TextBlock Grid.Column='0' Grid.Row='2' FontWeight='Bold' Width='30' Text='年齡'></TextBlock> <TextBox Grid.Column='1' Grid.Row='0' FontWeight='Bold' Width='100' /> <TextBox Grid.Column='1' Grid.Row='1' FontWeight='Bold' Width='100'/> <TextBox Grid.Column='1' Grid.Row='2' FontWeight='Bold' Width='100'/> </Grid> </Window>
上述xaml是我設(shè)計了一個三行兩列的界面,運行之后顯示如下:
在此,我沒有寫一行c#代碼,但是它竟然可以運行,所以也可以說它也是一種編程語言。只不過它更關(guān)注界面上面的東西而已。
那么它的運行是如何產(chǎn)生的?下面看幾個東西:
x:Class='MyXaml.Window1' ——利用class特性指定c#類名(后臺c#代碼)
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml——這表示利用x代替XAML的命名空間。用于包含特定的關(guān)鍵字和System.Windows.Markup中類型的子集。
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation——另一個命名空間。映射諸多wpf.net命名空間(system.windows.xxx,是個一對多的映射,主要封裝了三個程序集中,WindowsBase.dll、Presentation.dll和PresentationFramework.dll)
2.1 啟動
程序啟動的地方,其實是在程序的App.xaml文件里面:
<Application x:Class='MyXaml.App' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' StartupUri='Window1.xaml'> <Application.Resources> </Application.Resources> </Application>
看下面這句:
StartupUri='Window1.xaml'
這個就是程序的入口點,運行程序之后,我們就將window1顯示在了顯示屏上。
3.XAML語法概述
上述xaml中,顯示的一個核心布局就是以下這些代碼:
<Grid> <Grid.RowDefinitions> <RowDefinition Height='30'/> <RowDefinition Height='30'/> <RowDefinition Height='30'/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width='Auto'/> <ColumnDefinition Width='*'/> </Grid.ColumnDefinitions> <TextBlock Grid.Column='0' Grid.Row='0' FontWeight='Bold' Text='姓名:' Width='30'/> <TextBlock Grid.Column='0' Grid.Row='1' FontWeight='Bold' Width='30'>性別:</TextBlock> <TextBlock Grid.Column='0' Grid.Row='2' FontWeight='Bold' Width='30' Text='年齡'></TextBlock> <TextBox Grid.Column='1' Grid.Row='0' FontWeight='Bold' Width='100' /> <TextBox Grid.Column='1' Grid.Row='1' FontWeight='Bold' Width='100'/> <TextBox Grid.Column='1' Grid.Row='2' FontWeight='Bold' Width='100'/> </Grid>
1、看Grid控件,這個在wpf中是一個布局控件,就跟將窗體設(shè)置單元格差不過,可以依據(jù)它的row和column屬性來設(shè)置行和列。上述設(shè)置了一個三行兩列的布局。
2、看TextBlock和TextBox控件,這些都是一些顯示控件,一個顯示條和一個文本框,wpf中除此之外,還有許多的控件。
首先需要再確認的一點,那就是在C#中一切皆對象。如此一來,也就好理解了。
在XAML中的這些形形色色的控件其實就是一個個的類,我們應(yīng)用了他們就相當于是應(yīng)用了一個個的對象,而他們之中定義的一些width、height等屬性,就是這些類中封裝的一些屬性字段。
當然,像上面TextBox和TextBlock中的Grid.Column='1' Grid.Row='2'等屬性,其實并不屬于這兩個類中的屬性和字段。
而使得他們具備這樣屬性的,無疑就是外面的Grid布局控件賦予的,而在WPF中這樣的功能實現(xiàn)叫做附加屬性,是依賴屬性的一個特殊的用法。關(guān)于依賴屬性,在以后會詳細的討論。
第一個總結(jié)
WPF的XAML語法其實可以理解成另外一種形式的編程語言,其語法表現(xiàn)形式和XML類似,但是更嚴謹和更要求準確性。
XAML主要包括布局和控件,以此來構(gòu)建各種形態(tài)的應(yīng)用程序,除此之外,其中還有許多新的強大的東西,使得它更靈活和方便,例如依賴屬性。
3.1 布局
WPF中的布局常用的主要包括五種:Canvas、Grid、StackPanel、DockPanel和WrapPanel。下面分別說一下這五種布局控件的使用。
1、 Canvas
要說Canvas,先看以下的xaml代碼:
<Canvas> <Button Name='btn1' Height='100' Width='100' Content='btn1' Margin='10'/> <Button Name='btn2' Height='100' Width='100' Content='btn2' Margin='10'/> </Canvas>
然后,查看在畫布Canvas上面生成的畫面,情況如下:
為什么不顯示btn1?因為兩個button重疊了起來,只顯示最上面的控件(越接近結(jié)束標簽 </Canvas>的控件,如果兩個button的位置顛倒一下,顯現(xiàn)出來的就是btn1).
Canvas的布局基本就和之前的Winform一致了,都是以左上角為中心,按照上下距離左上角的坐標為標準的。如果想要改變button的位置,就要給button控件設(shè)置Canvas.Left、 Canvas.Top、Canvas.Bottom 和Canvas.Right這四個屬性。
所以Canvas得重點在絕對布局,對要求不太高的界面和比較固定的界面可以用這樣的方式拖拽控件布局。
2、 Grid
WPF窗體程序的默認布局就是一個Grid,先看如下代碼:
<Grid> <Button Name='btn1' Height='100' Width='100' Content='btn1' Margin='10'/> <Button Name='btn2' Height='100' Width='100' Content='btn2' Margin='10'/> </Grid>
看到這里,你也許會說,這不是和上面的Canvas一樣嗎?但是真的一樣嗎?他們的窗體如下所示:
相信你一定看出來了,不錯,和Canvas不同,Grid窗體默認的顯示是以中心為基準的,不像Canvas布局是以左上角為標準。
那么Grid布局有什么樣的好處呢?看下面這些代碼:
<Grid> <Grid.RowDefinitions> <RowDefinition Height='*'/> <RowDefinition Height='*'/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width='*'/> <ColumnDefinition Width='*'/> </Grid.ColumnDefinitions> <Button Name='btn1' Height='40' Width='40' Content='btn1' /> <Button Grid.Row='1' Grid.Column='1' Name='btn2' Height='40' Width='40' Content='btn2' /> </Grid>
然后在看看生成的窗口:
相信你一定可以看明白,知道Grid是把窗體分成了一塊塊的網(wǎng)格,而分割這個功能是通過Grid.RowDefinitions和Grid.ColumnDefinitions兩組屬性定義的,分別在其中定義了行和列,將窗體分為了幾行幾列,行的高度和列的寬度可以根據(jù)Width屬性設(shè)置。
如上圖,利用xaml定義了一個兩行兩列的Grid,并且在第0行0列放置btn1(如不顯示定義,則拖入的控件默認放在此網(wǎng)格。),第1行1列放置了btn2.
關(guān)于網(wǎng)格屬性做以下幾個說明。
RowDefinition 表示網(wǎng)格的行,其只有一個Height屬性而沒有Width屬性,*表示該行占據(jù)窗體剩下的所有的高度,如都設(shè)為*則表示平分窗體。如上所示,你還可以讓窗體3:1,只要將兩個行定義分別設(shè)置為3*和*就可以了。
ColumnDefinition 表示網(wǎng)格的列,其中只有一個Width屬性而沒有Height屬性,*號的用法同RowDefinition的用法,不過相對RowDefinition分割窗體的高度而言,在這里*表示分割窗體的寬度。
可以說,Grid實現(xiàn)的是一種網(wǎng)格布局,這種布局是相當強大的,可以并且用起來也非常靈活。
3、 StackPanel
StackPanel布局遵循的默認原則是從窗口中間部位,從頂部開始,從上到下排列控件。先看下面代碼:
<StackPanel> <Button Name='btn1' Height='40' Width='40' Content='btn1' /> <Button Name='btn2' Height='40' Width='40' Content='btn2' /> </StackPanel>
表現(xiàn)出來的窗體如下:
如上圖所示,控件的布局默認是豎向布局,那么如何設(shè)置控件橫向布局呢?我們只需要設(shè)置StackPanel的Orientation屬性就可以了:
Orientation='Horizontal' 橫向布局,從窗體中部,左側(cè)開始從左向右排列控件。
Orientation='Vertical'縱向布局,默認屬性。
橫向布局的實例如下:
<StackPanel Orientation='Horizontal'> <Button Name='btn1' Height='40' Width='40' Content='btn1' /> <Button Name='btn2' Height='40' Width='40' Content='btn2' /> </StackPanel>
窗口顯示:
4、 DockPanel
Dockpanel默認布局原則,從左中位置開始,控件依次排列,最后一個控件將剩余區(qū)域從中心填充。看下面代碼:
<DockPanel> <Button Name='btn1' Height='40' Width='40' Content='btn1' /> <Button Height='40' Width='40' Content='btn2' /> <Button Height='40' Width='40' Content='btn2' /> <Button Height='40' Width='40' Content='btn2' /> <Button Height='40' Width='40' Content='btn2' /> <Button Height='40' Width='40' Content='btn2' /> </DockPanel>
該布局的窗體顯示如下:
同StackPanel不同,Dockpanel布局依靠的是它的四個附加在其余控件上的附加屬性,看下表:
DockPanel.Dock屬性 |
說明 |
Top |
頂部,如果設(shè)置,從中間頂部開始依照上述原則布局 |
Left |
左部,默認布局 |
Right |
右部,如果設(shè)置,從中間右側(cè)開始依照上述原則布局 |
Button |
底部,如果設(shè)置,從中間底部開始依照上述原則布局 |
看下面實例,xaml代碼:
<DockPanel> <Button DockPanel.Dock="Bottom" Name="btn1" Height="40" Width="40" Content="btn1" /> <Button DockPanel.Dock="Bottom" Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> </DockPanel>
界面表現(xiàn)如下:
有上述描述代碼可知,此處StackPanel從底部開始布局兩個btn,在剩余的空間中(窗體上部),然后從默認位置左部開始依次放置btn,最后一個btn將最后剩余的空間填充。
5、 WrapPanel
WrapPanel布局遵循的原則是從窗體左上角開始,多控件的自動換行。同StackPanel一樣,它也有表示縱向和橫向的Orientation屬性。看下面xaml代碼:
<WrapPanel> <Button Name="btn1" Height="40" Width="40" Content="btn1" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> <Button Height="40" Width="40" Content="btn2" /> </WrapPanel>
生成的界面如下:
由此可知,WrapPanel默認的布局是橫向,等到右邊沒有空余,其余的控件將從第二行開始重新排列。
如果將其Orientation屬性設(shè)置Vertical那么排列將會從左上角開始,從上到下排列,下面沒有空余將會從第二行開始從上而下重新排列。如下xaml:
<WrapPanel Orientation="Vertical"> <Button Name="btn1" Height="40" Width="40" Content="btn1" /> <Button Height="30" Width="40" Content="btn2" /> <Button Height="30" Width="40" Content="btn2" /> <Button Height="30" Width="40" Content="btn2" /> <Button Height="30" Width="40" Content="btn2" /> </WrapPanel>
窗體布局如下:
由上可知,WrapPanel主要提供的功能是從窗體左上角開始,多控件的自動換行。
第二個總結(jié):
WPF中的布局除此之外還有如下的幾種:abPanel, ToolBarOverflowPanel, ToolBarPanel, UniformGrid, VirtualizingPanel, VirtualizingStackPanel,它們都派生于Panel抽象類,內(nèi)容屬性Children可以添加多個控件。它們藉此來控制控件的布局。
3.2 控件
其實布局也是控件的一種,但是單獨講布局列出來。因為布局在WPF中占據(jù)著異常重要的地位。接下來,主要說一下其他的控件,大體上,除了布局之外的控件可以分為以下的三類。
第一類:核心用戶輸入控件,用戶創(chuàng)建用戶界面的核心。其中比較常用的有Button、RadioButton、ComboBox、CheckBox、DataGrid、ListBox、ListView、TreeView、TextBlock、TextBox、Label。
第二類:窗口修飾控件,這些元素用于裝飾Window對象的框架。其中常用的有Menu、ToolBar、StatusBar、ToolTip、ProgressBar。
第三類:媒體控件,支持音頻/視頻的重放和圖像的顯示。其中比較常用的控件有Image、MediaElement、SoundPlayerAction。
下面分別說說每類控件的基本功能。
一、 核心用戶輸入控件
1、 Button、RadioButton,Button控件的基礎(chǔ)用法,主要是處理單擊Button的時候?qū)螕羰录幚淼姆绞健utton的單擊事件是通過Click特性聲明,其模式主要有三種:
Release:Button被按下然后松開時發(fā)生單擊事件
Hover: 鼠標懸停在按鈕上方引發(fā)單擊事件
Press:當單擊按鈕時引發(fā)單擊事件
我們可以利用Button單擊事件的模式設(shè)置我們想要的點擊控件的效果。
Button是內(nèi)容控件,我們可以給它的內(nèi)容設(shè)置其他的東西,比如下面的代碼,就是給一個Button按鈕設(shè)置圖片:
<Button x:Name="ImageButton" Margin="3" Grid.Row="1" HorizontalAlignment="Left"> <StackPanel Margin="1" Orientation="Horizontal" Width="620"> <Image Source="back.bmp" Stretch="UniformToFill" Width="160"/> <TextBlock Width="130" /> <TextBlock Text="圖片按鈕" Margin="1,15,1,1"/> </StackPanel> </Button>
除此之外,我們還可以給Button設(shè)置不同的樣式,使得它變得好看。涉及到了樣式、模板和觸發(fā)器,在此不過多陳述。
RadioButton和Button都是繼承自ButtonBase類,所具有的基本屬性是相同的,用法也大同小異。
2、 ComboBox控件,表示帶有下拉列表的選擇控件,通過單擊控件上的箭頭可顯示或隱藏下拉列表。用法如下:
<ComboBox> aaa </ComboBox>
其中Item表示下拉項,可以自己設(shè)定也可以通過Binding獲得。界面編輯器在ComboBox的屬性里面有一個Items集合,用來設(shè)定ComboBox的選項。Binding所用到的屬性是ItemsSource屬性。效果如下圖:
ComboBox控件選中事件可以從其選中項的SelectedItem的屬性來binding事件處理邏輯。
3、 CheckBox控件,表示用戶可以選擇并清除的控件。其用法形式如下:
<CheckBox> Content </CheckBox>
效果如下圖所示:
CheckBox控件主要用來處理三個事件,選中事件Checked、Unchecked,以及影響外觀的Indeterminate事件,可以分別在后臺顯示三者的處理邏輯。
<CheckBox x:Name="cb1" Grid.Row="1" Margin="5,0,0,0" Content="Three-state CheckBox" IsThreeState="True" Checked="HandleCheck" Unchecked="HandleUnchecked" Indeterminate="HandleThirdState" />
4、 DataGrid、ListBox、ListView、TreeView,都是用來以行列形式顯示的控件,前三個都是幾行幾列的形式,而最后一個TreeView則是顯示出來一種樹形結(jié)構(gòu)。
以上幾種控件可以用來進行數(shù)據(jù)綁定xml數(shù)據(jù)或者是數(shù)據(jù)庫,每一種都有不同的形式。基本的顯示圖如下所示:
TreeView:
而TextBox也可以用來做數(shù)據(jù)綁定,可以關(guān)聯(lián)其他的控件對象,來實現(xiàn)想要顯現(xiàn)的效果。
核心用戶輸入控件,除了上面列出來的這些之外,還有許多,例如:Calendar、Slider、TabControl等等,它們一起構(gòu)成了WPF的完整的輸入控件族,是用戶創(chuàng)建界面的核心。
二、 窗口修飾控件
1、 Menu控件,菜單控件,相信大家都不陌生,先看下面的xaml:
<Grid> <Menu> <MenuItem Header="First" > <MenuItem Header="second"/> <MenuItem Header="secend"> <MenuItem Header="third" Click="Handler"/> </MenuItem> </MenuItem> </Menu> </Grid>
顯示的界面:
由此可以看出,菜單控件是利用MenuItem子項形成層級結(jié)構(gòu),并且可以為每一個菜單項設(shè)置Click事件。上面實例沒有設(shè)置菜單的高度,故而菜單鋪滿全局。
菜單項有幾個屬性需要注意一下上圖中可以看出,一個子菜單主要有三個部分,其中一個是顯示內(nèi)容,內(nèi)容前面有個空白(這是一個圖標Icon的占位空白),還有子項后面的那個黑色的三角箭頭。
Icon:可以設(shè)置菜單的圖標,其內(nèi)容可以是一個image空間,用法如下:
<MenuItem.Icon> <Image Source="Delete.png"/> </MenuItem.Icon>
其中source指向你想要顯示為Icon的圖片。
Header:菜單的內(nèi)容,設(shè)置如上的xaml所示。
2、 ToolBar控件,工具條菜單。ToolBar 是一個 HeaderedItemsControl 。其內(nèi)容屬性為 Items 和 ItemsSource ,其標頭屬性為 Header 。基本用法看下面xaml:
<ToolBarTray Background="White"> <ToolBar Band="10" BandIndex="10"> <Button> <Image Source="Ore.jpg" /> </Button> <Separator/> <Button> <Image Source="Ore.jpg" /> </Button> </ToolBar> </ToolBarTray>
其中Separator表示分隔條,可以為工具條中的每個按鈕設(shè)計單擊事件打開某一程序。
工具條默認顯示為橫向,如果想要縱向顯示需要設(shè)置工具條的Orientation屬性。
工具條大概顯示如下:
4、 ToolTip控件, Tooltip控件是一個簡單,但非常有用的控件。它能夠為我們的軟件提供非常漂亮的提示信息,提高軟件的可用性,給用戶比較好的體驗。上xaml:
<Button Height="25" Content="提示工具演示" HorizontalAlignment="Center"> <Button.ToolTip> <ToolTip Background="#60AA4030" Foreground="White" HasDropShadow="False" Placement="Mouse"> <StackPanel> <TextBlock Margin="3">提示語:這是什么?</TextBlock> <!--<Image Source="black.jpg" Stretch="Fill"/>--> <TextBlock Margin="3">傳說中的3億網(wǎng)站。</TextBlock> </StackPanel> </ToolTip> </Button.ToolTip> </Button>
5、 ProgressBar控件,進度條。進度條有兩個屬性Minimum和Maximum,可以用這兩個屬性綁定事件來實現(xiàn)進度條的進展操作。一般情況下,進度條用于啟動時間過長需要等待而給用戶帶來的一個視覺加載效果。
其中有個IsIndeterminate屬性設(shè)置進度條的進度動畫,設(shè)為TRUE的時候,會顯示進度信息。默認情況是FALSE。
三、 媒體控件
2、 MediaElement控件,在WPF 中可以使用MediaElement 為應(yīng)用程序添加媒體播放控件,以完成播放音頻、視頻功能。由于MediaElement 屬于UIElement,所以它同時也支持鼠標及鍵盤的操作。
3、 SoundPlayerAction控件, WPF定義了一個SoundPlayerAction類(繼承自TriggerAction),它用一種友好的方式封裝了SoundPlayer類。這樣做的好處是,可以在控件的EventTrigger中添加SoundPlayerAciton動作,進而可以播放音頻文件。
例如:
<Button Content="xirihanlin"> <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <SoundPlayerAction Source="BLOW.WAV"/> </EventTrigger> </Button.Triggers> </Button>
有SoundPlayerAction類的一個好處是你不用為播放音頻文件而在后臺書寫代碼。但是,這樣的好處也會給你帶來限制,因為你根本無法控制SoundPlayerAction與SoundPlayer之間的交互。
當點擊Button時,會創(chuàng)建SoundPlayerAction對象,而SoundPlayerAction內(nèi)部構(gòu)建了一個SoundPlayer實例,并把SoundPlayerAction的Source屬性值傳給了SoundPlayer實例,并調(diào)用了SoundPlayer的Play,而事實上,由于音頻文件沒有提前加載,你將不能在點擊的同時就能聽見聲音。因此,使用SoundPlayerAction類的限制還包括無法提前加載文件和設(shè)置循環(huán)播放等。
相關(guān)文章
C# Windows API應(yīng)用之基于FlashWindowEx實現(xiàn)窗口閃爍的方法
這篇文章主要介紹了C# Windows API應(yīng)用之基于FlashWindowEx實現(xiàn)窗口閃爍的方法,結(jié)合實例形式分析了Windows API函數(shù)FlashWindowEx的功能、定義及實現(xiàn)窗口閃爍的相關(guān)技巧,需要的朋友可以參考下2016-08-08一種c#深拷貝方式完勝java深拷貝(實現(xiàn)上的對比分析)
下面小編就為大家?guī)硪黄环Nc#深拷貝方式完勝java深拷貝(實現(xiàn)上的對比分析)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-07-07