WPF高級教程(九)控件

定義

能夠與用戶交互的元素。繼承自System.Windows.Control,基類提供以下能力:

  • 設置對齊方式
  • 設置Tab順序
  • 背景,前景,邊框
  • 文本內容尺寸和字體

注意在有時候,我們會在描述的時候說:這是界面上的一個控件,這是界面上的一個元素,那麼,控件和元素有什麼關係和區別呢?實際上,界面上的可視化的內容就是元素,而能夠接受焦點並且能與用戶交互的元素叫做控件,所以元素的概念包含控件。這點大家瞭解即可。

控件的分類

  • 內容控件,能夠嵌套元素,無限擴展顯示。比如Button,Label等,大部分控件都是內容控件
  • 帶標題的內容控件,包括TabItem,GroupBox
  • 文本控件,允許輸入文本,密碼或者富文本的控件,比如TextBox
  • 列表控件,ListBox
  • 基於範圍的控件,ProgressBar
  • 日期控件,Calendar,DatePicker

內容控件

包含單個嵌套元素的控件,這也是跟佈局容器不同的地方。下面是內容控件的層級結構
在這裏插入圖片描述

  • 佈局容器在Panel基類上提供了Children集合保存所有的子控件,而內容控件在基類上提供了Content控件來接收單個元素
  • Content屬性的顯示:如果其屬性值繼承自UIElement,則繪製出來,如果不是繼承自UIElement,則直接調用ToString方法顯示。這就是界面上出錯的時候顯示一串類型名的原因
  • Window元素不允許被放到內容控件中
  • HasContent判斷控件中是否有內容
  • ContentTemplete用於告訴控件如何顯示他不識別的對象,數據模板在之後學習
    // 直接給內容控件的Content賦值
    <BUtton>
        <Image/>
    </Button>
    // 嵌套多個元素
    <BUtton>
        <StackPanel>
            <Image/>
            <Image/>
            <Image/>
        </StackPanel>
    </Button>
    
  • 在外層控件給內容的對齊方式需要使用HorizontalContentAlignment屬性設置
  • 在外層控件使用Padding屬性給內容添加內邊距
  • 按鈕內置的細節如陰影背景,圓角邊框這些不能通過在按鈕中改變內容來改變,需要使用控件模板來改變這些設定。
  • 自此,我們提到了兩個模板,數據模板ContentTemplate和控件模板,數據模板用於告訴控件如何顯示他不識別的對象,控件模板用於改變控件原有的行爲。

帶標題的內容控件

帶標題的內容控件是在內容控件的基礎上,原有的Content不變,新增了一個Header屬性,具體的例子在下面實例中介紹。

文本控件

  • TextBox 繼承自TextBoxBase,只存儲字符串
  • RichTextBox 繼承自TextBoxBase,存儲複雜元素FlowDocument
  • PasswordBox 繼承自Control,內部使用SecureString

列表控件

  • 列表控件繼承自ItemsControl
  • 使用列表控件最好配合數據綁定使用

基於範圍的控件

  • 基於範圍的控件包括 ScrollBar ProcessBar Slider
  • 基於範圍的控件繼承自 RangeBase
  • RangeBase提供以下屬性
    在這裏插入圖片描述
  • 通常不使用ScrollBar,而是使用其包裝版本ScrollViewer

日期控件

  • 日期控件有兩個 Calendar日曆 DatePicker 時間選擇控件,日曆控件會顯示一個日曆,時間選擇控件只會彈出一個選擇框,在點擊選擇按鈕的時候纔會彈出可以選擇的日曆

  • 日期控件的屬性很類似,如下圖

    在這裏插入圖片描述
    在這裏插入圖片描述

控件屬性

前景色,背景色

WPF中分別用Background和Foreground來設置背景色和前景色

  • 需要給對象設置Brush對象作爲值,Brush支持單一顏色,漸變色等。具體的畫刷使用我們在後面專門介紹
  • 代碼設置畫刷
    lbl_source.Background = new SolidColorBrush(Colors.AliceBlue);
    // 從SystemColors中獲取顏色
    lbl_source.Background = new SolidColorBrush(SystemColors.ControlColor);
    // 直接使用畫刷
    lbl_source.Background = SystemColors.ControlBrush;
    // 通過RGB設置
    byte red = 0;
    byte green = 255;
    byte blue = 0;
    lbl_source.Background = new SolidColorBrush(Color.FromRgb(red, green, blue));
    // 通過ARGB設置帶部分透明的顏色
    // 255 不透明 0 透明
    byte alpha = 100;
    lbl_source.Background = new SolidColorBrush(Color.FromArgb(alpha, red, green, blue));
    // 除了RGN標準,還有一套支持更多顏色的 scRGB 標準,這個標準支持更多的顏色,輸入的rgb值也從byte變成了float型
    
  • XAML中設置顏色
    <!--直接設置控件背景色-->
    <Button Background="Red" Content="Button" HorizontalAlignment="Left" Height="24.014" Margin="24.19,276.828,0,0" VerticalAlignment="Top" Width="105.453"/>
    <!--用較長方式設置,與上面的方式等價,但是如果設置的Brush不是SolidColorBrush就必須用下面的格式-->
    <Button  Content="Button" HorizontalAlignment="Left" Height="24.014" Margin="24.19,320.68,0,0" VerticalAlignment="Top" Width="105.453">
        <Button.Background>
            <SolidColorBrush Color="Red"></SolidColorBrush>
        </Button.Background>
    </Button>
    <!--使用RGB值-->
    <Button  Content="Button" Background="#FF0000" HorizontalAlignment="Left" Height="24.014" Margin="24.19,365.576,0,0" VerticalAlignment="Top" Width="105.453" />
    <!--使用ARGB值-->
    <Button Content="Button" Background="#AAFF0000" HorizontalAlignment="Left" Height="24.014" Margin="170.362,365.576,0,0" VerticalAlignment="Top" Width="105.453" /> 
    

字體

在這裏插入圖片描述

// 設置字體
<Button FontFamily="Times New Roman"/>
cmd.FontFamily = "Times New Roman";
// 直接設置字體的加粗版本
<Button FontFamily="Times New Roman Bold"/>
// 設置字體族
<Button FontFamily="Times New Roman Bold, Arial"/>
// 獲取計算機全部字體
Fonts.SystemFontFamilies
  • 上劃線 下劃線需要設置TextDecorations:Baseline Overline Strikethrough Underline
  • 字體會繼承屬性,這樣窗口設置的字體全部窗口都會使用
  • 前景色繼承,背景色不繼承。這裏需要注意,背景色設置爲空是透明背景,從效果上來看跟繼承的效果一樣。
  • IsEnabled IsVisible AllowDrop 都是繼承屬性
  • 依賴項屬性是否繼承是由 FrameworkPropertyMetadata.Inherits 屬性控制
  • 爲了防止電腦沒有字體文件,需要添加字體文件到應用程序中
    // 添加字體文件到應用程序中
    1. 添加ttf到項目中,設置構建類型爲 Resource
    2. 使用該字體
    <Label FontFamily="./#Bayern"/>
    
  • WPF對於小尺寸文字(小於15)的顯示,會出現文本模糊的問題,爲了解決這個問題,我們需要使用 TextOptions.TextFormattingMode=“Display”,而超過15個設備無關像素的字不使用這個屬性效果更好

光標

// 設置爲小沙漏
this.Cursor = Cursors.Wait;
<Button Cursor="Help"/>
// 自定義光標
Cursor customCursor = new Cursor(Path.Combine(applicationDir, "stopwatch.ani"));
this.Cursor = customCursor;
// 注意Cursor對象不直接使用url資源語法
// 光標文件加載爲資源使用Stream
StreamResourceInfo sri = Application.GetResourceStream(new Uri("stopwatch.ani", UriKind.Relative));
Cursor customCursor = new Cursor(sri.Stream);
  • 父窗口要強制窗口上的元素全部使用自己的光標類型 ForceCursor = true
  • 應用程序中的全部窗口使用同一個光標類型 Mouse.OverrideCursor = Cursors.Wait,某一個窗口不受這個限制 Mouse.OverrideCursor = null

控件特點實例

Label標籤

Label標籤支持Target屬性

<Label Target="{Binding ElementName=txt_labelTarget}" Content="_Label" HorizontalAlignment="Left" Margin="685.673,32.846,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txt_labelTarget" HorizontalAlignment="Left" Height="21.24" Margin="752.522,32.846,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="154.891"/>

注意:

  • _Label表示L爲快捷鍵,用Alt+L即可選中名字叫txt_labelTarget的輸入框,如果想要真正輸入下劃線,需要雙下劃線。
  • TextBlock不支持此功能

Button

  • Button 繼承自ButtonBase
  • GridViewColumnHeader RepeatButton ToggleButton 都繼承自ButtonBase,GridViewColumnHeader是ListView上面可以單擊的標題,RepeatButton在按下的時候會一直觸發Click,用於滾動條上下微調按鈕,ToggleButton可以設置按下和釋放狀態,用於開關按鈕,工具欄等
  • CheckBox RadioButton 繼承自 ToggleButton
  • ButtonBase定義了Click事件
  • ButtonBase定義了ClickMode,默認爲ClickMode.Release,還可以設置Press,按下觸發,Hover,懸停一會就觸發
  • 支持使用下劃線設置快捷鍵
  • Button控件可以設置IsDefault作爲默認按鍵,IsCancel設置取消按鈕,按下Esc會觸發取消按鈕
  • Button擁有一個只讀的屬性IsDefaulted,他要爲true需要兩個條件,一是自身沒有焦點,一是當前有焦點的控件不接受Enter鍵輸入。這個時候按下回車鍵會觸發這個按鈕,這個屬性可以用於觸發器。
  • CheckBox有三種狀態,可以通過IsThreeState設置三種還是兩種狀態。
    <CheckBox IsChecked="{x:Null}"/>
    
  • RadioButton可以設置GroupName設置分組,如果不設置的時候,同一個容器中的單選按鈕默認一組,設置組名可以覆蓋該設置。

ToolTip

  • ToolTip是在FrameworkElement中定義的,所以只要是能放置到窗口上面的元素都可以擁有ToolTip
  • ToolTip樣式可以自定義
    <Button>
        <Button.ToolTip>
            <StackPanel>
            ...
            </StackPanel>
        </Button.ToolTip>
    </Button>
    
  • ToolTip不能接受焦點,所以不能在ToolTip中添加可以用戶交互的控件,如果想實現這個功能,需要使用Popup控件
  • 屬性值
    在這裏插入圖片描述
  • ToolTip的彈出位置可以靈活的控制,通過上圖的屬性可以設置如下效果
  • 關於ToolTip的一些屬性需要使用ToolTipService來設置,這樣設置的好處是,多個控件可以複用同一個ToolTipService,但是要注意的是,這個屬性不能被繼承,所以不能在父元素中設置一次ToolTipService以期能夠在所有的子元素中實現相同的ToolTip效果
    在這裏插入圖片描述

Popup

  • Popup和ToolTip都能超出窗口邊界
  • Popup的子元素存儲在Child中而不是Content中
  • Popup可以接收焦點
  • Popup不會自動顯示,需要設置IsOpen
  • Popup默認不會自動消失,如果要實現在其他地方點擊鼠標讓其消失的效果,需要設置Popup.StaysOpen爲false
  • Popup通過PopupAnimation控制進入效果,如果要使用動畫效果,需要設置AllowsTransparency爲true
  • Popup需要設置Background來讓其可見
<TextBlock HorizontalAlignment="Left" Margin="685.673,85.399,0,0" TextWrapping="Wrap" VerticalAlignment="Top">
    Popup <Run TextDecorations="Underline" MouseEnter="Run_MouseEnter">term</Run>
</TextBlock>
<Popup Name="popLink" StaysOpen="False" Placement="Mouse" MaxWidth="200"
       PopupAnimation="Slide" AllowsTransparency="True">
    <Border BorderBrush="Beige" BorderThickness="2" Background="White">
        <TextBlock Margin="10" TextWrapping="Wrap">
            For more information, see
            <Hyperlink NavigateUri="http://www.baidu.com">Baidu</Hyperlink>
        </TextBlock>
    </Border>
</Popup>

ScrollViewer

  • 默認滾動條都是顯示的,如果想讓滾動條按需自動顯示隱藏,需要設置VerticalScrollBarVisibility爲Auto
  • 不顯示滾動條可以將VerticalScrollBarVisibility設置爲Disable或者Hidden,Hidden的滾動條不顯示,但是仍然能通過滾輪或者上下鍵進行滾動,這個技巧在自定義滾動按鈕的時候可以用到
  • 水平滾動條的默認值爲隱藏
  • 我們可以通過編程控制滾動條向上向下微調 LineUp() LineDown(),或者向上向下翻頁PageUp() PageDown(),或者直接滑動到頂部和底部 ScrollToEnd ScrollToHome
  • 我們可以告訴滾動條其子元素知道如何滾動,其子元素需要繼承自IScrollInfo,需要將滾動條的CanContentScroll設置爲true,這樣滾動條的滾動方法就會引發子元素的滾動方法,進行子元素滾動。StackPanel實現了IScrollInfo接口,所以將StackPanel放在滾動條控件裏可以實現逐元素的滾動而不是逐像素的滾動。注意在實驗的時候一定要將滾動條控件的 CanContentScroll設置爲True,才能成功。這個技術在自定義面板的滾動中很有用。

GroupBox

最簡單的帶標題的內容控件,僅僅是擁有圓角的邊框和標題,注意,GroupBox也是內容控件,在其中放置多個元素還是需要使用佈局容器。

在這裏插入圖片描述

TabControl

<TabControl>
    <TabItem>
        <TabItem.Header>
            <Button>123</Button>
        </TabItem.Header>
        <Grid Background="#FFE5E5E5"/>
    </TabItem>
    <TabItem Header="Tab 2">
        <Grid Background="#FFE5E5E5"/>
    </TabItem>
</TabControl>
  • Header屬性可以單獨設置(帶標題的內容控件的特點)
  • 如果要使用代碼控制Tab顯示,需要設置TabItem的IsSelected屬性
  • Header也可以接受所有類型的元素,顯示方式和Content是一致的

Expander 擴展器

在這裏插入圖片描述

  • 設置IsExpanderd來改變擴展和收起狀態
  • 擴展方向可以設置,設置ExpandDirection屬性
  • 顯示和隱藏前觸發Expanded和Collapsed事件,這個事件的處理常用於延遲加載
  • 可以使用ScrollViewer來設置一個可以滾動的擴展區域
// 注意ScrollViewer要指定高度
<Expander Header="Two">
    <ScrollViewer Height="50">
    ...
    </ScrollViewer> 
</Expander>

TextBox

  • 默認單行文本,如果需要換行需要設置TextWrapping屬性爲Wrap或WrapWithOverflow
  • 設置最大最小行數,設置這個屬性可以實現一個隨着文字量的多少自動擴展的文本框 MaxLines MinLines
  • LineCount可以獲取文本中有多少行
  • 按下Enter的時候回車需要設置AcceptReturn
  • 按下Tab插入製表符需要設置AcceptTabs
  • 如果要阻止用戶修改,可以設置只讀IsReadOnly也可以直接禁用
  • 拖拽選中文字,需要關注 SelectionStart選擇開始位置 SelectionLength選擇長度 SelectedText選擇的文本 SelectionChanged事件
  • 拖動逐單詞選擇 AutoWordSelection
  • 控制是否支持撤銷 CanUndo
  • 在使用代碼控制文字的時候,將一系列操作使用BeginChange和EndChange包起來,就可以把這一系列操作當作一個操作進行撤銷
  • 拼寫檢查 SpellCheck.IsEnabled,默認 英語 德語 西班牙語。也可以設置自己的資源詞典,以期讓檢查跳過一些人名,或者專業術語。具體的使用規則如果用到可以再研究。

PasswordBox

  • PasswordBox不支持剪貼板
  • 內部使用SecureString存儲,存儲的密文是加密的,密鑰是隨即成成的
  • SecureString擁有Dispose方法,在調用了該方法之後,在內存中徹底清除密文,保證安全

ListBox

  • 需要多選,可以設置SelectionMode爲Multiple或者Extended
  • 雖然ListBox有一個ListBoxItem子元素,但是他足夠靈活,不一定非要放置ListBoxItem元素,只要元素繼承自UIElement就可以被顯示出來,但是內部,仍然是包裹了一層Item

ComboBox

  • ComboBox可以設置IsEditable屬性,讓他可以輸入
  • 輸入的時候,控件會根據列表中對象的ToString方法運行的結果進行匹配,而選中的顯示也是ToString運行的結果,這就導致了下拉中可以顯示圖片,但是選擇之後的顯示只能顯示純文本的問題
  • 關於這個問題的解決需要使用下面的樣式複寫原有的Combo樣式
    <ContentPresenter Content="{TemplateBinding SelectedItem}" ContentStringFormat="{TemplateBinding DisplayMemberPath}" 
                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"
                      ContentTemplate="{TemplateBinding ItemTemplate}"
                  />
    
    其中需要注意的是,我們需要使用SelectedItem去替換原有的SelectionBoxItem,需要使用ItemTemplate去替換SelectionItemBoxTemplate即可,解決辦法來自於ComboBox ItemTemplate only working in dropdown,我們在之後的模板和樣式的講解中將繼續研究這裏修改的本質原因。

Slider

  • 常用於音量調節按鈕等

  • 屬性如下圖


ProcessBar

  • 如果並不清楚一個過程多久才能完成,可以設置IsIndeterminate爲true,這時候顯示一個從左到右的循環脈衝
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章