WPF基礎知識、界面布局及控件Binding(轉)


WPF是和WinForm對應的,而其核心是數據驅動事件,在開發中顯示的是UI界面和邏輯關系相分離的一種開放語言。UI界面是在XAML語言環境下開發人員可以進行一些自主設計的前台界面,邏輯關系還是基於c#語言進行的邏輯設計。在使用WPF做項目的時候,免不了要對界面進行布局,同時需要對其中的控件進行綁定,本文主要是對這幾方面進行介紹。

 

首先介紹WPF的基礎知識:

 

1 XAML是什么?

XAML(Extensible Application Markup Language)即可擴展應用程序標記語言,是WPF技術中專門用於設計UI的語言。

2、XAML的文檔結構?

在程序員眼中,UI界面只是一個平面結構。但是從后台XAML代碼中看來,UI界面實際上是一個樹形邏輯結構。

3、XAML中屬性元素的理解?

屬性元素指的是某個標簽的一個元素對應的這個標簽的一個屬性,即以元素的形式來表達一個實例的屬性。XAML為對象屬性賦值語法有兩種:使用字符串進行簡單賦值;使用屬性元素進行復雜賦值。例如:

<Grid VerticalAlignment="Center" HorizontalAlignment="Center" >

        <Rectangle x:Name="rectangle" Width="200" Height="120">

            <Rectangle.Fill >

                <SolidColorBrush Color="Blue" />

            </Rectangle.Fill >

        </Rectangle>

    </Grid >

 

4、XAML中的標記擴展?

標記擴展就是一種特殊的Attribute=Value,特殊處在於Value是由一對花括號及其括起來的內容組成。XAML編譯器會對這樣的內容作出解析、生成相應的對象。

5、WPF中事件處理器?

WPF支持在XAML里為對象的事件指定事件處理器,方法是使用事件處理器的函數名為對應對象事件的Attribute進行賦值。例如:

<Button x:Name="button1" Click=" button1_Click" Margin="5" Height="15" Width="50"/>

6、在自己的程序里引用類庫?

步驟需要三步:

1編寫類庫項目並編譯得到.dll文件或者獲得別人編譯的.dll文件。

2將類庫項目或者.dll文件中引用自己的項目

3在c#和XAML中引用類庫中的名稱空間。

 

7、XAML注釋語法?

<!—注釋內容-->

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

 

10、X名稱空間大致可分為三類?

Attribute:是語言層面的東西、是給編譯器看的。(Property是面向對象層面的東西,是給編程邏輯用的)

標記擴展:實際上就是一些MarkupExtension類的直接或者間接派生類。X名稱空間中就包含這樣的類。

XAML指令元素:有x:Code,x:XData。

11、WPF中控件?

經常用到的6類:

1 布局控件 可以容納多個控件或嵌套其他布局控件,用於在UI上組織和排列控件。常用的Grid、StackPanel、DockPanel,共同父類是Panel。

 2 內容控件 只能容納一個其他控件。父類是ContentControl。

 3 帶標題內容的控件 就是一個內容控件+一個標題,標題部分可容納一個控件或布局。

 4 條目控件 可以顯示一列數據,共同父類是ItemsControl。

 5 帶標題條目控件 就是一個條目控件+一個標題顯示區。基類是HeaderedItemsControl。

 6 特殊內容控件

 

12、WPF精髓?

WPF是數據驅動UI,數據是核心、主動的,UI屬於數據並表達數據、被動的

 

13、Binding是什么?

在WPF中,Binding是架在目標(UI層控件對象)和源(邏輯層對象)之間的一座橋梁。

14、Binding對源的要求是:只要它是一個對象,並且通過屬性公開自己的數據,它就能作為Binding的源。

 

15、Binding的方向即Binding模式有哪些?

Binding模式有OneWay、TwoWay、OnTime、OneWayToSource、Default。

OneWay:每當源發生變化時,數據就會從源流向目標。

TwoWay:綁定會將源數據發送到目標,但如果目標屬性發生變化,則會將變化發回給源。

OnTime:綁定會將源數據發送到目標,但是僅當啟動了應用程序或DataContext發生更改時才會有這個操作,所以它不會偵聽源中的更改通知。

OneWayToSource:綁定會將源數據發送到目標。

Default:根據實際情況來定,可編輯的就是TwoWay,只讀的就是OneWay。在連接沒有設置模式時就是Ddfault。

 

16、Binding的路徑(Path)和沒有Path的情況?

Binding的路徑設置有很多種,其中最簡捷的就是直接把Binding關聯在Binding源上。

<TextBox x:Name=”textBox1” Text={Binding Path=Value, ElementName=slider1}/>

沒有Path的情況就是Binding源本身就是數據且不需要Path來指明。

17、為Binding指定Source的幾種方法?沒有Source的情況?

(幾種方法,在這里不一一羅列,但是沒有實際用過。)

沒有Source的情況就是使用DataContext作為Binding的源。

18、Binding的數據校驗?Binding的數據轉換?

Binding數據有效性校驗是它的ValidationRules屬性,Binding數據轉換是它的Converter屬性。

 

19、模板 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));
            }
        }
    }
復制代碼

1、在前台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;

 

2、將控件作為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" />

 

3、使用集合對象作為列表控件的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);
復制代碼

  

 

都是一些基礎,謹供學習。

原文:http://www.cnblogs.com/ysyn/p/3408201.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM