主頁 > .NET開發 > WPF之控制元件布局

WPF之控制元件布局

2021-02-11 06:06:27 .NET開發

目錄
  • 控制元件概述
  • WPF的內容模型
  • 各類內容模型詳解
    • ContentControl族
    • HeaderedContentControl族
    • ItemsControl族
      • ListBox:在XAML中添加資料
      • ListBox:在代碼中添加資料
    • HeaderedItemsControl族
    • Decorator族
    • TextBlock和TextBox
    • Shape族元素
    • Panel族元素
  • UI布局(Layout)
    • 布局元素
    • Grid
      • 定義Grid的行與列
      • 行高和列寬的單位
      • 行高和列寬的取值
      • 為控制元件指定行和列遵循的規則
    • StackPanel
    • Canvas
    • DockPanel
    • WrapPanel
  • 總結
  • 參考資料

控制元件概述

程式的本質是“資料+演算法”——用戶輸入原始資料,演算法處理原始資料并得到結果資料,程式可以使用LED陣列、格式字串、圖形化用戶界面(Graphic User Interface,GUI)將結果資料顯示給用戶,其中圖形化用戶界面最方便、直觀,
在Windows上實作圖形化的界面有多種方法,每種方法又擁有自己的一套開發理念和工具并組成一種方法論,常見的有:

  • Windows APl(Win APl):呼叫Windows底層繪圖函式,使用C語言,最原始也最基礎,
  • Microsoft Foundation Class(MFC):使用C++語法將原始的Win32API函式封裝成控制元件類,
  • Visual Component Library(VCL):Delphi和C++Builder使用的與MFC相近的控制元件類別庫,
  • Visual Basic+ActiveX控制元件(VB6):使用組件化的思想把WinAPI封裝成UI控制元件,以期多語言共用,
  • Java Swing/AWT:Java SDK中用于跨平臺開發GUI程式的控制元件類別庫,
  • Windows Form:.NET平臺上進行GUl開發的老牌勁旅,完全組件化但需要.NET運行時支持,
  • Windows Presentation Foundation(WPF):后起之秀,使用全新的資料驅動UI的理念,

可以把上述這些方法論分為四代:

  • WinAPI時代:函式呼叫+Windows訊息處理,
  • 封裝時代:使用面向物件理念把WinAPI封裝成類;由來自UI的訊息驅動程式處理資料,
  • 組件化時代:使用面向組件理念在類的基礎上封裝成組件;訊息被封裝成事件,變成事件驅動,
  • WPF時代:在組件化的基礎上,使用專門的UI設計語言并引入由資料驅動UI的理念,

注:目前流行使用前端的方式實作GUI,如Electron、NanUI等,

WPF中是資料驅動UI,資料是核心、是主動的;UI從屬于資料并表達資料、是被動的,WPF把那些能夠展示資料、回應用戶操作的UI元素稱為控制元件(Control),控制元件所展示的資料稱之為控制元件的“資料內容”,控制元件在回應用戶的操作后會執行自己的一些方法或以事件(Event)的形式通知應用程式稱之為控制元件的“行為”或“演算法內容”

WPF中的控制元件是個非常抽象的概念——Control是資料和行為的載體,而無需具有固定的形象,如只要是用來顯示一個bool型別值并允許用戶通過單擊來切換true/false/null的UI元素就是一個CheckBox(關注抽象的資料和行為而不是控制元件具體的形象),

日常作業中打交道最多的控制元件無外乎6類,即:

  • 布局控制元件:可以容納多個控制元件或嵌套其他布局控制元件,用于在UI上組織和排列控制元件,如Grid、StackPanel、DockPanel 等控制元件(共同的父類是Panel),
  • 內容控制元件:只能容納一個其他控制元件或布局控制元件作為它的內容,如Window、Button等控制元件(經常需要借助布局控制元件來規劃其內容,共同父類是ContentControl),
  • 帶標題內容控制元件:相當于一個內容控制元件,但可以加一個標題(Header),標題部分亦可容納一個控制元件或布局,GroupBox、Tabltem等是這類控制元件的典型代表(共同父類是HeaderedContentControl),
  • 條目控制元件:可以顯示一列資料,一般情況下這列資料的型別相同,此類控制元件包括ListBox、ComboBox等(共同基類是ltemsControl,在顯示集合型別資料方面功能非常強大),
  • 帶標題條目控制元件:相當于一個條目控制元件加上一個標題顯示區,Tree Viewltem、Menultem都屬于此類控制元件(往往用于顯示層級關系資料,結點顯示在其Header區域,子級結點則顯示在其條目控制元件區域,共同基類是HeaderedltemsControl),
  • 特殊內容控制元件:這類控制元件相對比較獨立,比如TextBox容納的是字串、TextBlock可以容納可自由控制格式的文本、Image容納圖片型別資料,

6類控制元件的派生關系如下圖所示:

WPF是構建在.NET Framework上的一個子系統,它也是一個用于開發應用程式的框架(Framework),FrameworkElement的Framework指的就是WPF Framework,而FrameworkElement類在UIElement類的基礎上添加了很多專門用于WPF開發的API(比如SetBinding方法),所以從這個類開始才算是進入WPF開發柜架,

WPF的內容模型

根據是否可以裝載內容、能夠裝載什么樣的內容,WPF的UI元素可以分為如下型別:

名稱 注釋
ContentControl 單一內容控制元件
HeaderedContentControl 帶標題的單一內容控制元件
ltemsControl 以條目集合為內容的控制元件
HeaderedltemsControl 帶標題的以條目集合為內容的控制元件
Decorator 控制元件裝飾元素
Panel 面板類元素
Adorner 文字點綴元素
Flow Text 流式文本元素
TextBox 文本輸入框
TextBlock 靜態文字
Shape 圖形元素

控制元件的內容可以直接是資料,也可以是控制元件,當控制元件的內容還是控制元件的時候就形成了控制元件的嵌套(UI布局時尤為常見),被嵌套的控制元件稱為子級控制元件,所以WPF的UI會形成一個樹形結構,

  • 邏輯樹(Logical Tree):不考慮控制元件內部的組成結構,只觀察由控制元件組成的“樹”,
  • 可視元素樹(Visual Tree):WPF控制元件往往是由更基本的控制元件構成的(控制元件本身就是一棵樹),連控制元件本身的樹也考慮在內,比邏輯樹更“繁茂”的樹,

控制元件是記憶體中的物件,控制元件的內容也是記憶體中的物件,控制元件通過自己的某個屬性參考著作為其內容的物件,這個屬性稱為內容屬性(Content Property),“內容屬性”是個統稱,具體到每種控制元件上,內容屬性都有自己確切的名字——Content、Child、Items或Children,

控制元件的內容屬性與XAML標簽的內容存在一定的對應關系,XAML標簽的內容區域專門映射了控制元件的內容屬性,下面從語法和常理來解釋一下:

  • 嚴格按照語法來說,控制元件有內容屬性,在XAML里就應該能夠使用Atribute=Value 或者屬性標簽的形式來為內容賦值,如:
<Button Content="OK"/> 
<!--或-->
<Button>
  <Button.Content>
    <sys:String>OK</sys:String>
  </Button.Content>
</Button>
  • 按照常理來說,控制元件對應到XAML檔案里就是標簽,控制元件的內容就應該是標簽的內容、子級控制元件就應該是標簽的子級元素(簡稱標簽的元素),標簽的內容是夾在起始標簽和結束標簽間的代碼,上面的代碼可以寫成:
<Button>
  <sys:String>OK</sys:String>
</Button>

各類內容模型詳解

把符合某類內容模型的UI元素稱為一個族,每個族用它們共同基類來命名

ContentControl族

本族元素的特點如下:

  • 均派生自ContentControl類,
  • 它們都是控制元件(Control),
  • 內容屬性的名稱為Content,
  • 只能由單一元素充當其內容

“只能由單一元素充當其內容”以Button為例,Buton只能接受一個元素作為它的Content,需要一個帶圖示、文字的Button時要先用一個可以包含多個元素的布局控制元件把圖片和文字包裝起來,再把這個布局控制元件作為Buton的內容(控制元件的內容也可以是控制元件),

ContentControl族包含的控制元件:Button、ButtonBase、CheckBox、ComboBoxItem、ContentControl、Frame、GridViewColumnHeader、GropItem、Label、ListBoxItem、ListViewItem、NavigationWindow、RadioButton、RepeatButton、ScrollViewer、StatusBarItem、ToggleButton、ToolTip、UserControl、Window,

HeaderedContentControl族

本族元素的特點如下:

  • 它們都派生自HeaderedContentControl類,HeaderedContentControl是ContentControl類的派生類,
  • 它們都是控制元件,用于顯示帶標題的資料,
  • 除了用于顯示主體內容的區域外,控制元件還具有一個顯示標題(Header)的區域,
  • 內容屬性為Content和Header,
  • 無論是Content 還是Header都只能容納一個元素作為其內容,

HeaderedContentControl族包含的控制元件:Expender、GroupBox、HeaderedContentControl、TabItem,
下面演示一個以圖示為Header、以文字為主體內容的GroupBox,代碼如下:

<!--GroupBox.Content標簽可以省略-->
<GroupBox Margin="10" BorderBrush="SlateBlue">
    <GroupBox.Header>
        <Image Source="img.jpg" Width="20" Height="20"></Image>
    </GroupBox.Header>
    <GroupBox.Content>
        <TextBlock TextWrapping="WrapWithOverflow" Margin="10" Text="測驗內容"></TextBlock>
    </GroupBox.Content>
</GroupBox>

ItemsControl族

本族元素的特點如下:

  • 均派生自ItemsControl類,
  • 它們都是控制元件,用于顯示串列化的資料,
  • 內容屬性為Items或ItemsSource,
  • 每種ItemsControl都對應有自己的條目容器(Item Container)

本族的包含的控制元件:Menue、MenuBase、ContextMenu、ComboBox、ItemsControl、ListBox、ListViewe、TabControl、TreeView、Selector、StatusBar,對應的Item Container如下:

ItemsControl名稱 對應的Item container
ComboBox ComboBoxItem
ContextMenu MenuItem
ListBox ListBoxItem
ListView ListViewItem
Menu MenuItem
StatusBar StatusBarItem
TabControl TabItem
TreeView TreeViewItem

下面列出屬于ItemsControl族元素和其對應的Item Container有ComboBox——ComboBoxItem,ContextMenu——MenuItem,ListBox——ListBoxItem,ListView——ListViewItem,Menu——MenuItem,StatusBar——StatusBarItem,TabControl——TabItem,TreeView——TreeViewItem.

ListBox:在XAML中添加資料

ListBox除了可以顯示中規中矩的字串條目還能夠顯示更多的元素,如CheckBox、RadioButton、TextBox等,例如下面這段代碼:

<!--ListBoxItem標簽已省略-->
<ListBox x:Name="listbox" Margin="5">
    <CheckBox x:Name="chb1" Content="選擇1"/>
    <CheckBox x:Name="chb2" Content="選擇2"/>
    <CheckBox x:Name="chb3" Content="選擇3"/>
    <CheckBox x:Name="chb4" Content="選擇4"/>
    <Button x:Name="btn1" Content="按鈕1"/>
    <Button x:Name="btn2" Content="按鈕2"/>
    <Button x:Name="btn3" Content="按鈕3"/>
</ListBox>

表面看上去是ListBox直接包含了一些CheckBox和Buton,實際上這些CheckBox和Buton的父級容器是ListBoxItem,為按鈕添加如下的事件代碼查看父容器:

private void btn1_Click(object sender, RoutedEventArgs e)
{            
    Button btn = (sender) as Button;
    DependencyObject level1 = VisualTreeHelper.GetParent(btn);
    DependencyObject level2 = VisualTreeHelper.GetParent(level1);
    DependencyObject level3 = VisualTreeHelper.GetParent(level2);

    StringBuilder sbr = new StringBuilder();
    sbr.AppendLine("level1:"+level1.GetType().ToString());
    sbr.AppendLine("level2:" + level2.GetType().ToString());
    sbr.AppendLine("level3:" + level3.GetType().ToString());           
    MessageBox.Show(sbr.ToString());    
} 

ListBox:在代碼中添加資料

除非串列里的元素自始至終都是固定的才使用這種直接把UI元素作為ItemsControl內容的方法,如日期等,大多數情況下,UI上的串列會用于顯示動態的后臺資料,此時交給ltemsControl的就是程式邏輯中的資料了,在代碼中為ListBox添加資料的代碼如下:

<Grid>
    <ListBox x:Name="listbox" Margin="5"/>
</Grid>
List<Employee> empList = new List<Employee>()
{
    new Employee(){Id = 1, Name ="Tim", Age = 30},
    new Employee(){Id = 2, Name="Tom",Age=26},
    new Employee(){Id = 3,Name="Guo",Age=26},
    new Employee(){Id = 4,Name="Yan",Age=25},
    new Employee(){Id = 5,Name="Owen",Age=30},
    new Employee(){Id=6,Name="Victor",Age=30 }
};

this.listbox.DisplayMemberPath = "Name"; 
this.listbox.SelectedValuePath = "Id"; 
this.listbox.ItemsSource= empList;

//Employee類
public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}
  • DisplayMemberPath:這個屬性告訴ListBox顯示每條資料的哪個屬性,ListBox會去呼叫這個屬性值的ToString()方法,把得到的字串放入一個TextBlock(最簡單的文本控制元件),然后再按前面說的辦法把TextBlock包裝進一個ListBoxItem里,
  • SelectedValuePath:這個屬性將與其SelectedValue屬性配合使用,當呼叫SelectedValue屬性時ListBox先找到選中的Item所對應的資料物件,然后把SelectedValuePath的值當作資料物件的屬性名稱并把這個屬性的值取出來

DisplayMemberPath 和Selected ValuePath 是兩個相當簡化的屬性,DisplayMemberPath只能顯示簡單的字串,想用更加復雜的形式顯示資料需要使用DataTemplate;SelectedValuePath也只能回傳單一的值,如果想進行一些復雜的操作可直接使用ListBox的SelectedItem和SelectedItems屬性,這兩個屬性回傳的是資料集合中的物件

HeaderedItemsControl族

本族控制元件*除了具有ItemsControl的特性外,還具顯示標題的能力**,本族元素的特點如下:

  • 均派生自HeaderedItemsControl類,
  • 它們都是控制元件,用于顯示串列化的資料,同時可以顯示一個標題,
  • 內容屬性為Items、ItemsSource和Header,

本族控制元件只有3個:MenuItem、TreeViewItem、ToolBar

Decorator族

本族中的元素是在UI上起裝飾效果的,本族元素的特點如下:

  • 均派生自Decorator類,
  • 起UI裝飾作用,
  • 內容屬性為Child,
  • 只能由單一元素充當內容,

本族元素有:ButtonChrome、ClassicBorderDecorator、ListBoxChrome、SystemDropShadowChrome、Border、InkPresenter、BulletDecorator、Viewbox、AdornerDecorator,

可以使用Border元素為一些組織在一起的內容加個邊框,使用ViewBox元素讓組織在一起的內容能夠自由縮放

TextBlock和TextBox

兩個控制元件最主要的功能是顯示文本:

  • TextBlock只能顯示文本,不能編輯,又稱靜態文本,可以使用豐富的印刷級的格式控制標記顯示專業的排版效果,由于需要操縱格式它的內容屬性是Inlines(印刷中的“行”),同時也保留一個名為Text的屬性(當簡單地顯示一個字串時可以使用)
  • TextBox則允許用戶編輯其中的內容,由于不需要太多的格式顯示它的內容是簡單的字串,內容屬性為Text

TextBlock屬于比較底層的控制元件,因此它的性能要比Label好一些,如果需求只是純文本的顯示,并且不提供Access key的支持,那么TextBlock是個不錯的選擇,

Shape族元素

Shape族元素(只是簡單的視覺元素,不是控制元件)是專門用來在UI上繪制圖形的一類元素,本族元素的特點如下:

  • 均派生自Shape類,
  • 用于2D圖形繪制,
  • 無內容屬性
  • 使用Fill屬性設定填充,使用Stroke屬性設定邊線

注:該族控制元件一般較少使用,用于自定義控制元件外觀,

Panel族元素

所有用于UI布局的元素都屬于這一族,本族元素的特點如下:

  • 均派生自Panel抽象類
  • 主要功能是控制UI布局,
  • 內容屬性為Children
  • 內容可以是多個元素,Panel元素將控制它們的布局,

ItemsControl和Panel元素內容都可以是多個元素,但ItemsControl強調以串列的形式來展現資料而Panel則強調對包含的元素進行布局,所以ItemsControl的內容屬性是Items和ItemsSource而Panel的內容屬性名為Children,

本族元素有:Canvas、DockPanel、Grid、TabPanel、ToolBarOverflowPanel、StackPanel、ToolBarPanel、UniformGrid、VirtualizingPanel|VirtualizingStackPanel、WrapPanel,

UI布局(Layout)

WPF的布局是依靠各種布局元素實作的,

布局元素

WPF中的布局元素有如下幾個:

  • Grid:網格,可以自定義行和列并通過行列的數量、行高和列寬來調整控制元件的布局,近似于HTML中的Table,
  • StackPanel:堆疊式面板,可將包含的元素在豎直或水平方向上排成一條直線,移除元素時后面的元素會自動向前移動填充空缺
  • Canvas:畫布,內部元素可以使用以像素為單位的絕對坐標進行定位,類似于Windows Form編程的布局方式,
  • DockPanel:泊靠式面板,內部元素可以選擇泊靠方向,類似于在Windows Form編程中設定控制元件的Dock屬性
  • WrapPanel:自動折行面板,內部元素在排滿一行后能夠自動折行,類似于HTML中的流式布局,

Grid

Grid元素會以網格的形式對內容元素們(即它的Children)進行布局,
Grid的特點如下:

  • 可以定義任意數量的行和列,非常靈活,
  • 行的高度和列的寬度可以使用絕對數值、相對比例或自動調整的方式進行精確設定,并可設定最大和最小值,
  • 內部元素可以設定自己的所在的行和列,還可以設定自己縱向跨幾行、橫向跨幾列,
  • 可以設定Children元素的對齊方向,

Grid適用的場合有:

  • UI布局的大框架設計
  • 大量UI元素需要成行或者成列對齊的情況,
  • UI整體尺寸改變時,元素需要保持固有的高度和寬度比例
  • UI后期可能有較大變更或擴展,

定義Grid的行與列

Grid類具有ColumnDefinitions和RowDefinitions兩個屬性,分別是ColumnDefinition和RowDefinition的集合,表示Grid定義了多少列、多少行,
XAML代碼如下:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>            
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
</Grid>

C#代碼如下:

//添加列
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
//添加行
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());

行高和列寬的單位

計算機圖形設計的標準單位是像素(Pixel),所以Grid的寬度和高度單位就是像素,此外,Grid還接受英寸(Inch)、厘米(Centimeter)和點(Point),如下表所示:

英文名稱 中文名稱 簡寫 換算
Pixel 像素 px(默認單位,可省略) 圖形基本單位
Inch 英寸 in 1inch=96pixel
Centimeter 厘米 cm 1cm=(96/2.54)pixel
Point pt 1pt=(96/72)pixel

實際使用如下所示:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="30px"/>
        <RowDefinition Height="30"/>
        <RowDefinition Height="0.5in"/>
        <RowDefinition Height="1cm"/>
        <RowDefinition Height="30pt"/>
    </Grid.RowDefinitions>
</Grid>
  • 屬性的值為double型別
  • 因為像素是默認單位,所以px可以省略
  • 其他單位也會被轉換成像素并顯示在Grid的邊緣處

行高和列寬的取值

對于Grid的行高和列寬,可以設定三類值:

  • 絕對值:double數值加單位后綴(如上例),一經設定就不會再改變,又稱固定值,適用于當控制元件的寬度和高度不需要改變或者使用空行、空列作為控制元件間隔時
  • 比例值:double數值后加一個星號(“*”),比例值的最終像素數=比例值的數值/所有比例值的數值和*未被占用空間的像素數,當改變容器的尺寸時使用比例值的行高會保持固有比例,行高和列寬的默認形式就是比例值,沒有顯式指定行高或列寬時默認值就是1*(1*又可以簡寫為*)
  • 自動值:字串Auto,行高或列寬的實際值將由行列內控制元件的高度和寬度決定,控制元件會把行列“撐”到合適的寬度和高度,行列中沒有控制元件時行高和列寬均為0

為控制元件指定行和列遵循的規則

  • 行和列都是從0開始計數
  • 指定一個控制元件在某行,就為這個控制元件的標簽添加Grid.Row=“行編號“這樣一個Attribute,若行編號為0(即控制元件處于首行)則可省略這個Attribute
  • 指定一個控制元件在某列,就為此控制元件添加Grid.Column=”列編號”這樣的Attribute,若列編號為0則Attribute可以者略不寫
  • 控制元件需要跨多個行或列,請使用Grid.RowSpan=“行數“和Grid.ColumnSpan=“列數“兩個Atribute

StackPanel

StackPanel可以把內部元素在縱向或橫向上緊湊排列、形成堆疊式布局,StackPanel適合的場合有:

  • 同類元素需要緊湊排列(如制作選單或者串列),
  • 移除其中的元素后能夠自動補缺的布局或者影片,

StackPanel使用Orientation、HorizontalAlignment和VerticalAlignment這3個屬性來控制內部元素的布局,如下所示:

屬性名稱 可取值 描述
Orientation Horizontal
Vertical
決定內部元素是橫向累積還是縱向累積
HorizontalAlignment Left
Center
Right
Stretch
決定內部元素水平方向上的對齊方式
VerticalAlignment Top
Center
Bottom
Stretch
決定內部元素豎直方向上的對齊方式

Canvas

Canvas譯成中文就是“畫布”,在Canvas里布局就像在畫布上畫控制元件一樣,使用Canvas布局與在Windows Form表單上布局基本上是一樣的,只是WPF的控制元件沒有Left和Top等屬性,當控制元件被放置在Canvas里時就會被附加上Canvas.X和Canvas.Y屬性

Canvas適用的場合包括:

  • 一經設計基本上不會再有改動的小型布局(如圖示),
  • 藝術性比較強的布局,
  • 需要大量使用橫縱坐標進行絕對點定位的布局,
<Canvas>
    <TextBlock Text="用戶名:" Canvas.Left="12" Canvas.Top="12"/>
    <TextBox Height="23" Width="200" BorderBrush="Black" Canvas.Left="66" Canvas.Top="19"/>
    <TextBlock Text="密碼:" Canvas.Left="12" Canvas.Top="40.72" Height="16" Width="36"/>
    <TextBox Height="23" Width="200" BorderBrush="Black" Canvas.Left="66" Canvas.Top="38"/>
    <Button Content="確定" Width="80" Height="22" Canvas.Left="100" Canvas.Top="67"/>
    <Button Content="清除" Width="80" Height="22" Canvas.Left="186" Canvas.Top="67"/>
</Canvas>

除非你確定這個視窗的布局以后不會改變而且表單尺寸固定,不然還是用Grid進行布局彈性會更好,

DockPanel

DockPanel內的元素會被附加上DockPanel.Dock這個屬性,這個屬性的資料型別為Dock列舉(可取Left、Top、Right和Bottom四個值),根據Dock屬性值,DockPanel內的元素會向指定方向累積、切分DockPanel內部的剩余可用空間,

DockPanel還有一個重要屬性——bool型別的LastChildFill(默認值是True),當LastChildFill屬性的值為True時,DockPanel內最后一個元素的DockPanel.Dock屬性值會被忽略,這個元素會把 DockPanel內部所有剩余空間充滿

實際使用如下:

<Grid>
    <DockPanel>
        <TextBox DockPanel.Dock="Top" Height="25" BorderBrush="Black" />
        <TextBox DockPanel.Dock="Left" Width="150" BorderBrush="Black"/>
        <TextBox BorderBrush="Black"/>
    </DockPanel>
</Grid>

WrapPanel

WrapPanel內部采用的是流式布局,使用Orientation屬性來控制流延伸的方向,使用HorizontalAlignment和VerticalAlignment 兩個屬性控制內部控制元件的對齊,在流延伸的方向上,WrapPanel會排列盡可能多的控制元件,排不下的控制元件將會新起一行或一列繼續排列,
實際使用如下:

<WrapPanel>
    <Button Width="50" Height="50" Content="OK"/>
    <Button Width="50" Height="50" Content="OK"/>
    <Button Width="50" Height="50" Content="OK"/>
    <Button Width="50" Height="50" Content="OK"/>
    <Button Width="50" Height="50" Content="OK"/>
    <Button Width="50" Height="50" Content="OK"/>
    <Button Width="50" Height="50" Content="OK"/>
    <Button Width="50" Height="50" Content="OK"/>
    <Button Width="50" Height="50" Content="OK"/>
    <Button Width="50" Height="50" Content="OK"/>
</WrapPanel>

總結

形而上者謂之道,形而下者謂之器,WPF的內部機理可以說是WPF的“道”,動手實踐寫程式可以說是WPF的“器”,

參考資料

WPF控制元件和布局
控制元件與布局(WPF)
WPF學習二:TextBlock和Label的區別

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/258599.html

標籤:WPF

上一篇:C#中word匯出功能騷操作

下一篇:C#控制臺對齊問題

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more