WPF是和WinForm對應的,而其核心是數據驅動事件,在開發中顯示的是UI界面和邏輯關係相分離的一種開放語言。UI界面是在XAML語言環境下開發人員能夠進行一些自主設計的前臺界面,邏輯關係仍是基於c#語言進行的邏輯設計。在使用WPF作項目的時候,免不了要對界面進行佈局,同時須要對其中的控件進行綁定,本文主要是對這幾方面進行介紹。程序員
首先介紹WPF的基礎知識:算法
1 XAML是什麼?編程
XAML(Extensible Application Markup Language)便可擴展應用程序標記語言,是WPF技術中專門用於設計UI的語言。canvas
二、XAML的文檔結構?c#
在程序員眼中,UI界面只是一個平面結構。可是從後臺XAML代碼中看來,UI界面其實是一個樹形邏輯結構。ide
三、XAML中屬性元素的理解?函數
屬性元素指的是某個標籤的一個元素對應的這個標籤的一個屬性,即以元素的形式來表達一個實例的屬性。XAML爲對象屬性賦值語法有兩種:使用字符串進行簡單賦值;使用屬性元素進行復雜賦值。例如:工具
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" >佈局
<Rectangle x:Name="rectangle" Width="200" Height="120">學習
<Rectangle.Fill >
<SolidColorBrush Color="Blue" />
</Rectangle.Fill >
</Rectangle>
</Grid >
四、XAML中的標記擴展?
標記擴展就是一種特殊的Attribute=Value,特殊處在於Value是由一對花括號及其括起來的內容組成。XAML編譯器會對這樣的內容做出解析、生成相應的對象。
五、WPF中事件處理器?
WPF支持在XAML裏爲對象的事件指定事件處理器,方法是使用事件處理器的函數名爲對應對象事件的Attribute進行賦值。例如:
<Button x:Name="button1" Click=" button1_Click" Margin="5" Height="15" Width="50"/>
六、在本身的程序裏引用類庫?
步驟須要三步:
1編寫類庫項目並編譯獲得.dll文件或者得到別人編譯的.dll文件。
2將類庫項目或者.dll文件中引用本身的項目
3在c#和XAML中引用類庫中的名稱空間。
七、XAML註釋語法?
<!—註釋內容-->
九、 XAML中X名稱空間?
X名稱空間映射的是xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
<Rectangle x:Name="rectangle" Width="200" Height="120">
<Rectangle.Fill >
<SolidColorBrush Color="Blue" />
</Rectangle.Fill >
</Rectangle>
十、X名稱空間大體可分爲三類?
Attribute:是語言層面的東西、是給編譯器看的。(Property是面向對象層面的東西,是給編程邏輯用的)
標記擴展:實際上就是一些MarkupExtension類的直接或者間接派生類。X名稱空間中就包含這樣的類。
XAML指令元素:有x:Code,x:XData。
十一、WPF中控件?
常常用到的6類:
1 佈局控件 能夠容納多個控件或嵌套其餘佈局控件,用於在UI上組織和排列控件。經常使用的Grid、StackPanel、DockPanel,共同父類是Panel。
2 內容控件 只能容納一個其餘控件。父類是ContentControl。
3 帶標題內容的控件 就是一個內容控件+一個標題,標題部分可容納一個控件或佈局。
4 條目控件 能夠顯示一列數據,共同父類是ItemsControl。
5 帶標題條目控件 就是一個條目控件+一個標題顯示區。基類是HeaderedItemsControl。
6 特殊內容控件
十二、WPF精髓?
WPF是數據驅動UI,數據是核心、主動的,UI屬於數據並表達數據、被動的。
1三、Binding是什麼?
在WPF中,Binding是架在目標(UI層控件對象)和源(邏輯層對象)之間的一座橋樑。
1四、Binding對源的要求是:只要它是一個對象,而且經過屬性公開本身的數據,它就能做爲Binding的源。
1五、Binding的方向即Binding模式有哪些?
Binding模式有OneWay、TwoWay、OnTime、OneWayToSource、Default。
OneWay:每當源發生變化時,數據就會從源流向目標。
TwoWay:綁定會將源數據發送到目標,但若是目標屬性發生變化,則會將變化發回給源。
OnTime:綁定會將源數據發送到目標,可是僅當啓動了應用程序或DataContext發生更改時纔會有這個操做,因此它不會偵聽源中的更改通知。
OneWayToSource:綁定會將源數據發送到目標。
Default:根據實際狀況來定,可編輯的就是TwoWay,只讀的就是OneWay。在鏈接沒有設置模式時就是Ddfault。
1六、Binding的路徑(Path)和沒有Path的狀況?
Binding的路徑設置有不少種,其中最簡捷的就是直接把Binding關聯在Binding源上。
<TextBox x:Name=」textBox1」 Text={Binding Path=Value, ElementName=slider1}/>
沒有Path的狀況就是Binding源自己就是數據且不須要Path來指明。
1七、爲Binding指定Source的幾種方法?沒有Source的狀況?
(幾種方法,在這裏不一一羅列,可是沒有實際用過。)
沒有Source的狀況就是使用DataContext做爲Binding的源。
1八、Binding的數據校驗?Binding的數據轉換?
Binding數據有效性校驗是它的ValidationRules屬性,Binding數據轉換是它的Converter屬性。
1九、模板 Template?
ControlTemplate是算法內容的表現形式;DataTemplate是數據內容的表現形式
20、DataTemplate經常使用到的3個地方:
ContentControl的ContentTemplate屬性,ItemsControl的ItemTemplate屬性,GrdiViewColumn的CellTemplate屬性。
WPF界面佈局
在WPF作項目過程當中,須要對界面元素進行合理佈局,以便系統更人性化。WPF提供了一套強有力的工具:面板panel。下面將逐一介紹這些面板的使用方法。
Grid
網格面板,以表格形式佈局元素,對於整個面板上的元素進行佈局,有效地解決多行之間、多列之間位置的一致性。Grid很像網頁中的Table,定義一個網格,須要定義行、列,劃分單元格,座標從(0,0)開始。列寬和行高,分別能夠在ColumnDefinition、RowDefinition裏面指定Width、Height的值。首先定義網格,而後定義元素,並指定元素所在的單元格。若是不定義單元格,默認將元素放到第一個單元格(0,0)。自動長度——自動匹配列中最長元素的寬度;比例長度——*表示佔用剩餘的所有寬度;兩行都是*,將平分剩餘寬度;一個2*,一個*,表示前者2/3寬度。使用Grid.ColumnSpan和Grid.RowSpan附加屬性可讓相互間隔的行列合併,使用GridSplit控件結合Grid控件實現相似於WinForm中SplitContainer的功能。
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="44*" /> <ColumnDefinition Width="141*" /> <ColumnDefinition Width="218*" /> <ColumnDefinition Width="122*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="62*" /> <RowDefinition Height="70*" /> <RowDefinition Height="102*" /> <RowDefinition Height="116*" /> </Grid.RowDefinitions> <Button Content="Button" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="16,18,0,0" Name="button1" VerticalAlignment="Top" Width="75" Grid.Column="1" /> <Button Content="Button" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="107,38,0,0" Name="button2" VerticalAlignment="Top" Width="75" /> <Button Content="Button" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="16,38,0,0" Name="button3" VerticalAlignment="Top" Width="396" Grid.ColumnSpan="3" Grid.Column="1" /> </Grid>
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="102" /> <ColumnDefinition Width="161" /> <ColumnDefinition Width="15" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="66" /> <RowDefinition Height="96" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> </Grid>
Canvas
畫布,用於徹底控制每一個元素的精確位置。它是佈局控件中最爲簡單的一種,直接將元素放到指定位置,主要來佈置圖畫。使用Canvas時,必須指定一個字元素的位置(相對於畫布),不然全部元素都將出如今畫布的左上角。調整位置用Left、Right、Top和Bottom四個附加屬性。若是Canvas是窗口主元素,用戶改變窗口大小時,Canvas也會隨之變化,字元素的位置也會隨之移動,以保證相對於Canvas的位置屬性不變。Canvas容許子元素的部分或所有超過其邊界,默認不會剪裁子元素,同時可使用負座標,所以畫布不須要指定大小。若是想複製畫布內容,將ClipToBounds設爲true便可。
<Grid> <Canvas Height="280" HorizontalAlignment="Left" Margin="22,32,0,0" Name="canvas1" VerticalAlignment="Top" Width="482" Background="Gray"> <Canvas Canvas.Left="46" Canvas.Top="58" Height="100" Name="canvas2" Width="200" Background="Red"> <Ellipse Canvas.Left="82" Canvas.Top="20" Height="100" Name="ellipse1" Stroke="Black" Width="200" Fill="White" /> </Canvas> <Canvas Canvas.Left="295" Canvas.Top="184" Height="64" Name="canvas3" Width="143" Background="Green" ClipToBounds="True" > <Ellipse Canvas.Left="24" Canvas.Top="7" Height="100" Name="ellipse2" Stroke="Black" Width="200" Fill="White" /> </Canvas > </Canvas> </Grid>
StackPanel
棧面板,能夠將元素排列成一行或者一列。其特色是:每一個元素各佔一行或者一列。Orientation屬性指定排列方式:Vertical(垂直)【默認】、Horizontal(水平)。默認狀況下,水平排列時,每一個元素都與面板同樣高;垂直排列時,每一個元素都與面板同樣寬。若是元素超過了StackPanel的空間,會截斷多出的內容。 元素的Margin屬性用於使元素之間產生必定得間隔,當元素空間大於其內容的空間時,剩餘空間將由HorizontalAlignment和VerticalAlignment屬性來決定如何分配。
<Grid> <StackPanel Height="144" HorizontalAlignment="Left" Margin="33,21,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="346"> <Button Content="Button" Height="23" Name="button1" Width="75" /> <Button Content="Button" Height="23" Name="button2" Width="235" /> <Button Content="Button" Height="23" Name="button3" Width="658" /> </StackPanel> <StackPanel Height="155" HorizontalAlignment="Left" Margin="45,179,0,0" Name="stackPanel2" VerticalAlignment="Top" Width="401" Orientation="Horizontal" > <Button Content="Button" Height="23" Name="button4" Width="75" /> <Button Content="Button" Height="23" Name="button5" Width="75" /> </StackPanel> </Grid>
WrapPanel
從左至右或從上至下按順序位置定位子元素,若是排滿則自動換行至下一行或列繼續排列。WrapPanel面板也提供了 Orientation屬性設置排列方式,屬性設置橫排(Horizontal默認)和豎排(Vertical)。
<Grid> <WrapPanel Height="129" HorizontalAlignment="Left" Margin="50,36,0,0" Name="wrapPanel1" VerticalAlignment="Top" Width="260"> <Button Content="Button" Height="23" Name="button1" Width="75" /> <Button Content="Button" Height="23" Name="button2" Width="75" /> <Button Content="Button" Height="23" Name="button3" Width="75" /> <Button Content="Button" Height="23" Name="button4" Width="75" /> </WrapPanel> <WrapPanel Height="105" HorizontalAlignment="Left" Margin="99,195,0,0" Name="wrapPanel2" VerticalAlignment="Top" Width="211" Orientation="Vertical" > <Button Content="Button" Height="23" Name="button5" Width="75" /> <Button Content="Button" Height="23" Name="button6" Width="75" /> </WrapPanel> </Grid>
DockPanel
停靠面板,能夠將面板的某一邊指定給每一個元素,當面板大小變化時,按鈕將根據指定的邊進行停靠。在DockPanel中,指定停靠邊的控件,會根據定義的順序佔領邊角,全部控件毫不會交疊。默認狀況下,後添加的元素只能使用剩餘空間,最後一個元素填充全部剩餘空間。若是不但願最後一個元素填充剩餘區域,能夠將DockPanel屬性LastChildFill設置爲False。
DockPanel面板能夠將子元素停靠在面板的上下左右。DockPanel會對每一個子元素進行排序,並停靠在面板的一側,多個停靠在同側的元素則按順序排序,最後一個元素填充這個Panel(這個須要設置LastChildFill屬性爲 True)。對於在DockPanel中的元素的停靠屬性能夠經過Panel.Dock的附加屬性來設置。
<Grid> <DockPanel Height="100" HorizontalAlignment="Left" Margin="43,44,0,0" Name="dockPanel1" VerticalAlignment="Top" Width="281" LastChildFill="False" > <Button Content="Button" Height="23" Name="button1" Width="75" /> <Button Content="Button" Height="23" Name="button2" Width="75" /> <Button Content="Button" Height="23" Name="button3" Width="75" /> </DockPanel> <DockPanel Height="141" HorizontalAlignment="Left" Margin="140,183,0,0" Name="dockPanel2" VerticalAlignment="Top" Width="299"> <Button Content="Button" Height="23" Name="button4" Width="75" /> <Button Content="Button" Height="23" Name="button5" Width="75" /> <Button Content="Button" Height="23" Name="button6" Width="75" /> </DockPanel> </Grid>
視圖框(Viewbox)
視圖框能夠自動縮放其內容,以填充可用的空間。它只能有一個子元素。好比,Viewbox中放置一個Canvas,默認將按比例縮放Canvas,填充區域,而此時Canvas指定的長寬已不起做用,僅保留比例。若是想禁用Viewbox的自動縮放功能,將其拉伸屬性Stretch設置爲None便可;若是想縮放而且不保留子元素比例,將Viewbox的Stretch屬性(默認爲Uniform)改成Fill(徹底填充);若是想保留比例並徹底填充空白區域,Stretch設置爲UniformToFill。
上圖分別是stretch:Stretch="Fill", Stretch="None",Stretch="Uniform",Stretch="UniformToFill"
<Grid>
<Canvas Height="261" HorizontalAlignment="Left" Margin="34,22,0,0" Name="canvas1" VerticalAlignment="Top" Width="416">
<Viewbox Canvas.Left="29" Canvas.Top="18" Height="218" Name="viewbox1" Width="348" Stretch="UniformToFill" >
<Button Content="Button" Height="23" Name="button1" Width="75" />
</Viewbox>
</Canvas>
</Grid>
Border
Border 是一個裝飾的控件,此控件繪製邊框及背景,在 Border 中只能有一個子控件(這個子控件又能夠包含多個子控件)。
<Grid> <Border BorderThickness="20" BorderBrush="Green" Height="230" HorizontalAlignment="Left" Background="Red" Margin="35,40,0,0" Name="border1" VerticalAlignment="Top" Width="447" /> </Grid>
滾動視圖控件(ScrollViewer)
滾動視圖控件能夠將過多的內容放入一個可滾動的區域來顯示。好比一個很大的橢圓,經過滾動就能夠顯示所有內容。可是ScollViewer只能放一個元素,這個元素是任意的。假若想佈局多個元素,能夠將多個元素放到一個面板中,再嵌入到ScollViewer中。
滾動條的可見性,默認垂直滾動條是可見的(Visiable),而水平滾動條是不可用的(Disable),此處改成Auto(須要時顯示)或者Visiable(可見,不論需不須要都顯示)。
UniformGrid
均佈網格, 顧名思義,全部單元格均勻排布,大小都相同。你能夠爲其指定行數Rows和列數Columns,UniformGrid將根據行列平分畫布,每一個控件一個單元格。若是不指定其行數和列數,UniformGrid會根據子元素個數和大小,默認建立相同的行數和列數,佈局全部子元素。因爲每一個單元格只包含一個子元素,不須要額外指定哪一個元素屬於哪一個單元格,因此直接添加子元素就能夠。
公共佈局屬性
Width、Height表示元素寬度和高度,設置該屬性能夠是元素具備精確的寬高。MinWidth、MaxWidth、MinHeight、MaxHeight 能夠指定元素大小的界限,分別表示元素的最小寬度、最大寬度、最小高度和最大高度。當你指定一個元素的寬度和高度時,WPF會盡量遵循你的設置。好比元素寬度>屏幕寬度,元素將被剪裁以適應可用空間。
Margin(外邊距),指的是元素周圍的距離,決定了元素周圍留下的空白大小;Padding(內邊距),指的是元素邊界與其內容之間的距離。作過網頁設計、用過CSS的同窗對margin和padding屬性確定不陌生,但也有所區別。WPF中的Margin值能夠爲一個數字、一對數字和四個數字。
一個數字表明四周距離相同,爲指定值。一對數字時,第一個數字表示左側和右側距離相同,爲指定值;第二個數字表示頂部和底部距離相同,爲指定值。(與CSS中順序不一樣)。四個數字,分別表示左側、頂部、右側、底部距離,該順序與CSS不一樣。
CSS中margin和padding屬性順序是:兩個數字對應左右、上下;四個數字對應上、右、下、左;
HorizontalAlignment與VerticalAlignment
在父元素中,當剩餘空間很大時(超過子元素須要),這兩個屬性能夠控制字元素的位置。好比,在垂直排列的StackPanel中,面板寬度默認和最寬的元素寬度相同,其餘控件的寬度默認將會被拉伸。這時,可使用HorizontalAlignment屬性來控制,默認值爲Stretch(拉伸),還有Left、Center、Right。VerticalAlignment則有Stretch、Top、Center和Bottom四個枚舉值。
Visibility可見度,決定元素是否可見。枚舉值有兩個:Collapsed和Hidden。Collapsed元素不可見,而且首選尺寸變爲0,再也不影響佈局。Hidden元素雖然不可見,但尺寸不變,佈局系統仍按可見的處理。
FlowDirection文本方向,默認狀況下基於系統的本地設置。好比英語、中文都是從左往右排列,LeftToRight;希伯來文從右往左排列,RightToLeft。若是爲面板指定該屬性,則面板的全部子元素都按此方向排列。
Panel.ZIndex,Panel定義的一個附加屬性ZIndex,用於多個元素重疊時,指定顯示的上下層關係。ZIndex值大的將出如今值小的元素上方。元素顯示順序將不受文檔定義順序控制。若是不使用ZIndex,重疊元素將根據文檔定義的順序顯示,後定義的元素出如今上方。
Binding基礎
首先,建立一個類Student,繼承INotifyPropertyChanged。定義幾個字段以及一個組件屬性更改引起的方法。貼代碼:
public class Student:INotifyPropertyChanged { private string name; public string Name { get { return name; } set { this.name = value; NotifyPropertyChanged("Name"); } } private int id; public int ID { get { return id; } set { this.id = value; NotifyPropertyChanged("ID"); } } public int age; public int Age { get { return age; } set { this.age = value; NotifyPropertyChanged("Age"); } } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
一、在前臺wpf界面定義一個button控件(btnBinding_Click),用以改變Name字段的值,將控件textbox(tbDisplay)綁定到Name字段。基本步驟:
(1)全部代碼都寫在後臺邏輯:
準備數據源:Student student = new Student();
準備Binding:
Binding binding = new Binding();
binding.Source = student;
binding.Path = new PropertyPath("Name");
使用Binding鏈接到數據源與Binding目標:BindingOperations.SetBinding(this.tbDisplay, TextBox.TextProperty, binding);
將上述三步操做合一:this.tbDisplay.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = student = new Student() });
(2)不過你們通常的作法是在前臺界面進行綁定,同時在後臺邏輯上指定綁定源,以下:
前臺綁定:<TextBox Height="23" HorizontalAlignment="Left" Margin="27,12,0,0" Name="tbDisplay" Text="{Binding Path=Name}" VerticalAlignment="Top" Width="120" />
後臺邏輯:
Binding bind = new Binding("Name") { Source = student };
this.tbDisplay.SetBinding(TextBox.TextProperty, bind);
(3)如今將其放在一個容器內進行綁定:
前臺綁定:<StackPanel Height="226" HorizontalAlignment="Left" Margin="790,36,0,0" Name="SP" VerticalAlignment="Top" Width="239" >
<TextBox x:Name="tbDisplay" Width="171" Height="47" Margin="5,100,10,100" Text="{Binding Path=Name}" />
</StackPanel >
後臺邏輯:Student student = new Student();
this.SP.DataContext = student;
二、將控件做爲binding源於binding標記擴展
全部操做都放在在前臺界面中:
<TextBox Height="23" HorizontalAlignment="Left" Margin="27,170,0,0" Name="tbNum" Text="{Binding Path=Value,ElementName=slider1}" VerticalAlignment="Top" Width="120" />
<Slider Height="23" HorizontalAlignment="Left" Margin="27,210,0,0" Name="slider1" VerticalAlignment="Top" Maximum="100" Minimum="0" Width="187" />
三、使用集合對象做爲列表控件的ItemsSource
下面這個例子是要把List<Student>集合的實例做爲ListBox的ItemsSource,同時讓ListBox顯示Student的Name並使用TextBox顯示當前選中的條目的ID。
前臺界面:
<TextBox Height="23" HorizontalAlignment="Right" Margin="0,52,571,0" Name="tbID" VerticalAlignment="Top" Width="120" />
<ListBox Height="100" HorizontalAlignment="Left" Margin="414,162,0,0" Name="lbStudent" VerticalAlignment="Top" Width="120" />
後臺的邏輯:
List<Student> stuList = new List<Student>() { new Student (){ID=0,Name="Tim",Age=23}, new Student (){ID=1,Name="Tom",Age=24}, new Student (){ID=2,Name="Mike",Age=25}, }; //爲listbox設置Binding this.lbStudent.ItemsSource = stuList; this.lbStudent.DisplayMemberPath = "Name"; //爲textbox設置Binding Binding binding = new Binding("SelectedItem.ID") { Source = this.lbStudent }; this.tbID.SetBinding(TextBox.TextProperty, binding);
都是一些基礎,謹供學習。
綁定補充: