柚子快報(bào)激活碼778899分享:c# WPF基礎(chǔ)應(yīng)用
柚子快報(bào)激活碼778899分享:c# WPF基礎(chǔ)應(yīng)用
WPF參考原文
MVVM介紹
1.常用布局控件
1.1 布局控件
WPF(Windows Presentation Foundation)提供了多種布局容器來幫助開發(fā)者設(shè)計(jì)用戶界面,以下是一些常用的布局:
Grid: Grid是最常用的布局容器之一,它允許你通過定義行和列以及對(duì)元素進(jìn)行定位來進(jìn)行布局。在Grid中,可以設(shè)置元素的邊距來控制其與其他元素的距離。StackPanel: StackPanel按照單一方向(垂直或水平)堆疊其子元素。子元素的寬度或高度將取決于其內(nèi)容,這使得它非常適合用來創(chuàng)建簡(jiǎn)單的列表或工具欄等。WrapPanel: WrapPanel允許子元素根據(jù)可用空間自動(dòng)換行。當(dāng)父容器的寬度被占滿時(shí),WrapPanel會(huì)自動(dòng)將后續(xù)的元素放置到新的一行。DockPanel: DockPanel允許子元素沿邊緣填充,或者在剩余空間中填充。這對(duì)于創(chuàng)建具有可變大小的工具欄和面板非常有用。Canvas: Canvas類似于坐標(biāo)系,所有的元素都通過坐標(biāo)來決定其在Canvas中的位置。使用Left、Top、Right、Bottom附加屬性可以在Canvas中定位控件。Border: Border用于為其他UI元素提供邊框,也可以包含背景顏色、背景圖片等。GroupBox, Expander, ViewBox: 這些布局提供了特定的功能,如分組控件、可展開/收縮的內(nèi)容區(qū)域以及縮放內(nèi)容以適應(yīng)可用空間。UniformGrid: UniformGrid將子元素均勻地分布在網(wǎng)格中,每一行和每一列都有相同數(shù)量的元素。FlowDocumentPageViewer: 用于顯示和管理XAML流文檔的頁(yè)面。ListBox, ListView, TreeView: 這些控件提供了列表和樹形結(jié)構(gòu)的數(shù)據(jù)展示方式。
1.1.1Grid、StackPanel、WrapPanel介紹
WPF中的Grid是一個(gè)功能強(qiáng)大的布局系統(tǒng),它允許開發(fā)者以表格的形式對(duì)UI元素進(jìn)行精確的定位和布局。
在WPF中,Grid控件由行和列組成,這些行和列的集合分別稱為行集合和列集合。開發(fā)者可以通過定義行(RowDefinitions)和列(ColumnDefinitions)的數(shù)量、大小以及其他屬性來創(chuàng)建復(fù)雜的布局結(jié)構(gòu)。以下是Grid的一些關(guān)鍵特性:
行列定義:使用RowDefinitions和ColumnDefinitions屬性來定義Grid的行數(shù)和列數(shù)。每個(gè)RowDefinition或ColumnDefinition對(duì)象可以設(shè)置高度或?qū)挾?,以及是否?qiáng)制其內(nèi)容適應(yīng)可用空間。元素定位:在Grid中,每個(gè)子元素的位置通過Grid.Row和Grid.Column附加屬性來指定,這些屬性的值是從0開始的索引數(shù)。例如,Grid.Row="1"和Grid.Column="2"將元素放置在第二行第三列的位置。對(duì)齊方式:Grid提供了多種對(duì)齊方式,如水平對(duì)齊(HorizontalAlignment)和垂直對(duì)齊(VerticalAlignment),以便靈活控制子元素在單元格中的位置。調(diào)試輔助:雖然Grid本身是設(shè)計(jì)為不可見的,但可以通過設(shè)置Grid.ShowGridLines屬性為True來顯示網(wǎng)格線,這有助于在設(shè)計(jì)時(shí)更清晰地觀察和調(diào)整布局。
2.樣式Style(只能定義修改系統(tǒng)預(yù)設(shè)的一些屬性)
介紹:在WPF中,樣式是一種可以重復(fù)使用的視覺元素集合,它用于定義控件的外觀和行為。以下是WPF中樣式的一些詳細(xì)說明:
樣式的定義與應(yīng)用 樣式通常在XAML中定義,并且可以通過設(shè)置控件的Style屬性來將其應(yīng)用到特定的UI元素上。一個(gè)樣式可以包含多個(gè)Setter元素,每個(gè)Setter指定一個(gè)屬性及其對(duì)應(yīng)的值。例如,可以創(chuàng)建一個(gè)樣式來設(shè)置按鈕的背景顏色、字體大小等屬性。樣式的作用范圍 樣式不僅可以定義單個(gè)控件的外觀,還可以通過屬性繼承影響整個(gè)窗口或應(yīng)用程序界面的視覺效果。例如,如果在窗口級(jí)別設(shè)置了字體屬性,那么窗口中的所有元素都將使用這些相同的屬性值。樣式與模板的區(qū)別 雖然樣式和模板都是用來控制控件外觀的機(jī)制,但它們之間存在一些差異。樣式主要用于定義控件的外觀屬性,而模板則提供了一種更深層次的定制能力,允許開發(fā)者改變控件的內(nèi)部結(jié)構(gòu)和行為。樣式的復(fù)用性 類似于CSS在Web開發(fā)中的作用,WPF中的樣式可以用來統(tǒng)一控制應(yīng)用程序中的視覺效果,提高代碼的復(fù)用性和可維護(hù)性。一旦創(chuàng)建了樣式,就可以在多個(gè)地方重復(fù)使用,而無需重復(fù)編寫相同的屬性設(shè)置代碼。
2.1內(nèi)部引用
<1>對(duì)于樣式資源,可以單獨(dú)定義在每個(gè)窗口中,中,但是只能被此窗口的控件對(duì)象所調(diào)用
內(nèi)聯(lián)樣式:這是直接在控件的XAML標(biāo)記中定義樣式的方式。例如,可以直接設(shè)置控件的Height、Width、Foreground、HorizontalAlignment等屬性。這種方法適用于樣式簡(jiǎn)單且僅在一個(gè)控件中使用的情況。資源字典:當(dāng)樣式較復(fù)雜或需要在多個(gè)控件中重用時(shí),可以將樣式定義為資源,并在需要使用該樣式的控件中通過鍵(Key)進(jìn)行引用。這種方式使得樣式集中管理,便于維護(hù)和修改。
2.1.1 樣式繼承
基礎(chǔ)用法: 通過定義一個(gè)基樣式,其他樣式可以通過繼承這個(gè)基樣式來應(yīng)用相同的設(shè)置。例如,如果我們有一個(gè)按鈕樣式baseButtonStyle,它設(shè)置了字體大小、前景色和背景色,我們可以創(chuàng)建一個(gè)新的樣式,讓它基于baseButtonStyle,然后添加或覆蓋特定的屬性。
2.2 外部引用
<2>如果想要所有窗口的對(duì)象均可調(diào)用,需要?jiǎng)?chuàng)建-》資源字典ResourceDictionary,并在App.xaml中進(jìn)行聲明
樣式文件引用:當(dāng)一個(gè)應(yīng)用程序中有多個(gè)窗口或用戶控件需要使用相同的樣式時(shí),可以將樣式寫在單獨(dú)的XAML文件中,然后在需要的窗口或用戶控件中引用這個(gè)樣式文件。這樣做的好處是可以減少代碼重復(fù),并使得樣式的管理更加模塊化。動(dòng)態(tài)資源:使用動(dòng)態(tài)資源可以在運(yùn)行時(shí)根據(jù)條件改變樣式,比如數(shù)據(jù)綁定的變化或者觸發(fā)器(Trigger)的觸發(fā)條件滿足時(shí)。動(dòng)態(tài)資源允許應(yīng)用程序更加靈活地適應(yīng)不同的場(chǎng)景和狀態(tài) 1.定義資源字典 2.在資源字典中定義樣式 3.在App.xaml中進(jìn)行資源字典引用 4.窗口中進(jìn)行樣式資源引用
3.設(shè)置ControlTemplate(可以設(shè)定除系統(tǒng)預(yù)設(shè)屬性之外的樣式)
(1)概念:當(dāng)我們不想使用某個(gè)控件他的系統(tǒng)預(yù)設(shè)外觀,想要自定義控件的外觀和樣式時(shí),就需要編寫控件的ControlTemplate。WPF 的 ControlTemplate 是一種用于定義和自定義控件的外觀和結(jié)構(gòu)的模板,它可以完全替換控件的默認(rèn)模板,實(shí)現(xiàn)個(gè)性化和復(fù)雜的效果。
(2)WPF 的 ControlTemplate 有以下幾個(gè)特點(diǎn):
ControlTemplate 是一個(gè) XAML 元素,它可以包含任何類型的 UI 元素,如布局、形狀、圖像、文本等,這些元素構(gòu)成了控件的視覺樹(VisualTree)。ControlTemplate 可以使用 TemplateBinding 或 Binding 來綁定控件的屬性或數(shù)據(jù),從而實(shí)現(xiàn)動(dòng)態(tài)的顯示和更新。ControlTemplate 可以使用 Triggers 來定義控件對(duì)不同的條件或事件的響應(yīng),如改變屬性、播放動(dòng)畫、執(zhí)行操作等。ControlTemplate 可以使用 ContentPresenter 或 ItemsPresenter 來呈現(xiàn)控件的內(nèi)容或子元素,從而保留控件的基本功能。ControlTemplate 可以在 Style 或 ResourceDictionary 中定義,并應(yīng)用到一個(gè)或多個(gè)控件上,從而實(shí)現(xiàn)資源的重用和管理。
(3)想要重塑一個(gè)控件,我們得先知道原來的控件是如何構(gòu)成編寫的。例如對(duì)于一個(gè)按鈕,我們可以創(chuàng)建一個(gè)WPF項(xiàng)目, 創(chuàng)建一個(gè)Button按鈕, 然后選中該按鈕, 右鍵選擇編輯模板>編輯副本。 創(chuàng)建完成后, 會(huì)在當(dāng)前頁(yè)面
4.觸發(fā)器Trigger
4.1單條件觸發(fā)器
屬性觸發(fā)器(Trigger): 當(dāng)控件的某個(gè)依賴屬性滿足特定條件時(shí),屬性觸發(fā)器會(huì)被激活。例如,當(dāng)按鈕被按下時(shí)改變其背景色。數(shù)據(jù)觸發(fā)器(DataTrigger): 與屬性觸發(fā)器類似,但監(jiān)測(cè)的是數(shù)據(jù)源屬性的變化而非控件屬性。當(dāng)綁定的數(shù)據(jù)滿足特定條件時(shí),數(shù)據(jù)觸發(fā)器會(huì)被激活。
<1>屬性(Property)觸發(fā)器
4.2多條件觸發(fā)器
多重觸發(fā)器(MultiTrigger): 這種觸發(fā)器包含多個(gè)條件,只有當(dāng)所有條件都滿足時(shí)觸發(fā)器才會(huì)生效。這允許你創(chuàng)建更復(fù)雜的條件組合來影響控件的外觀或行為。
4.3行為觸發(fā)器
事件觸發(fā)器(EventTrigger): 當(dāng)綁定的事件被觸發(fā)時(shí),事件觸發(fā)器會(huì)激活。例如,當(dāng)按鈕點(diǎn)擊事件發(fā)生時(shí)啟動(dòng)一個(gè)動(dòng)畫或其他操作。
5.數(shù)據(jù)綁定
5.1數(shù)據(jù)綁定模型
中文譯本將Data Binding譯為了數(shù)據(jù)綁定,很大程度上其實(shí)是拼音音譯,沒有實(shí)際意義。WPF中的Binding更多地是表達(dá)一種橋梁關(guān)系。Binding對(duì)象的兩端,分別是源(Source)和目標(biāo)(Target),源即數(shù)據(jù)來源,目標(biāo)就是數(shù)據(jù)要到達(dá)的地方。一般情況下,源一般是邏輯層的對(duì)象,目標(biāo)是UI層的控件對(duì)象,數(shù)據(jù)由源通過Binding對(duì)象送達(dá)UI層,也就完成的數(shù)據(jù)驅(qū)動(dòng)UI的過程。 如圖所示,數(shù)據(jù)綁定實(shí)質(zhì)上是綁定目標(biāo)與綁定源之間的橋梁。 該圖演示了以下基本的 WPF 數(shù)據(jù)綁定概念:
通常情況下,每個(gè)綁定具有四個(gè)組件:
綁定目標(biāo)對(duì)象(Binding Target - Dependency Object)目標(biāo)屬性(Dependency Property)綁定源(Binding Source - Object)指向綁定源中要使用的值的路徑(Path - Property)
例如,如果將 TextBox 的內(nèi)容綁定到 Employee.Name 屬性,則可以類似如下所示設(shè)置綁定:
目標(biāo) | TextBox目標(biāo)屬性 | Text源對(duì)象 | Employee源對(duì)象值路徑 | Name
結(jié)合圖像我們可以這樣理解:數(shù)據(jù)來源是Employee類的Name屬性,數(shù)據(jù)要去往的目標(biāo)是TextBox的Text屬性上,所以我們將TextBox的Text屬性綁定到Employee類的Name屬性上,當(dāng)我們從TextBox經(jīng)過Binding這座橋梁抵達(dá)源,也就是Employee類時(shí),再通過一段路徑走到Name屬性上。接下來我們來展開這個(gè)例子。
5.2使數(shù)據(jù)源具有通知能力
數(shù)據(jù)源是一個(gè)對(duì)象,一個(gè)對(duì)象上有很多數(shù)據(jù),外界通過屬性進(jìn)行訪問,這個(gè)屬性,就是要設(shè)置的路徑(Path),也就是要通過Binding送往UI元素的,或者說是UI元素所關(guān)心的哪個(gè)屬性值的變化。Binding要想實(shí)現(xiàn)數(shù)據(jù)流通,就需要讓這個(gè)屬性具備通知Binding屬性值發(fā)生變化的能力。解決方案就是在屬性的set塊中激發(fā)一個(gè)PropertyChanged事件。要想激發(fā)這個(gè)事件,就需要讓數(shù)據(jù)源的類實(shí)現(xiàn)System.ComponentModel命名空間中的INotifyPropertyChanged接口。這樣一來,當(dāng)我們綁定到這個(gè)數(shù)據(jù)源上時(shí),Binding對(duì)象就會(huì)自動(dòng)偵聽來自這個(gè)接口的PropertyChanged事件。
public class Employee:INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
string name;
public string Name
{
get { return name; }
set
{
name = value;
if(this.PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
}
當(dāng)類實(shí)現(xiàn)了INotifyPropertyChanged接口后,會(huì)自動(dòng)聲明PropertyChanged事件。在set塊下先判斷當(dāng)前事件是否被訂閱,若訂閱了,則當(dāng)屬性值發(fā)生變化時(shí),就會(huì)觸發(fā)事件。PropertyChanged 是一個(gè)委托,它是 INotifyPropertyChanged 接口的一個(gè)事件,用于通知綁定對(duì)象屬性的更改。
傳入PropertyChanged 的兩個(gè)參數(shù)一是事件源,在這里就是當(dāng)前這個(gè)事件;二是屬性變更事件參數(shù),也就是是哪個(gè)屬性要發(fā)生改變需要被監(jiān)聽,把名字報(bào)上來。
當(dāng)你在 XAML 中綁定了一個(gè)實(shí)現(xiàn)了 INotifyPropertyChanged 接口的類的屬性時(shí),PropertyChanged 事件就會(huì)被自動(dòng)訂閱,這樣當(dāng)屬性值發(fā)生變化時(shí),就會(huì)觸發(fā) PropertyChanged 事件,從而更新 UI 上的綁定值。所以我們需要判斷 PropertyChanged 是否為空,是為了避免在沒有訂閱事件的情況下調(diào)用它,否則會(huì)引發(fā)異常。
PropertyChanged 既是委托,也是事件。委托是一種類型,用于定義方法的簽名,可以將方法作為參數(shù)傳遞或賦值給變量。事件是一種特殊的委托,用于在某些情況發(fā)生時(shí)通知其他對(duì)象。事件通常是事件發(fā)送方的成員,例如 Click 事件是 Button 類的成員, PropertyChanged 事件是實(shí)現(xiàn) INotifyPropertyChanged 接口的類的成員。
對(duì)應(yīng)的屬性的類能夠?qū)崿F(xiàn)通知后,我們?cè)诖绑w的后臺(tái)代碼去實(shí)例化并使用這個(gè)類的對(duì)象。
public partial class MainWindow : Window
{
Employee employee = new Employee() { Name = "Default Name" };
public MainWindow()
{
InitializeComponent();
}
}
5.3實(shí)現(xiàn)綁定的后置代碼
擁有了源,以及UI元素作為目標(biāo)后,我們要使用Binding對(duì)象連通源和目標(biāo)。
public partial class MainWindow : Window
{
Employee employee = new Employee() { Name = "Default Name" };
public MainWindow()
{
InitializeComponent();
Binding binding = new Binding();
binding.Source = employee;
binding.Path = new PropertyPath("Name");
BindingOperations.SetBinding(this.InputTextBox, TextBox.TextProperty, binding);
}
}
在這里,employee作為數(shù)據(jù)源,InitializeComponent()是用于初始化UI元素的代碼。先實(shí)例化Binding對(duì)象,并設(shè)置源和路徑,最后使用BindingOperations.SetBinding()實(shí)現(xiàn)數(shù)據(jù)源與目標(biāo)鏈接,其三個(gè)參數(shù)為:
目標(biāo)對(duì)象:要作為目標(biāo)的UI控件或其他對(duì)象。目標(biāo)的依賴屬性:要注意的是,這里傳入的不是對(duì)象的屬性,而是一個(gè)靜態(tài)只讀的依賴屬性(DependencyProperty)成員變量,依賴屬性我們會(huì)在下一節(jié)講解。Binding對(duì)象:指定用于連接的Binding對(duì)象。
例如對(duì)于下面這個(gè)程序,我們額外設(shè)置了一個(gè)按鈕用于輸出當(dāng)前Employee對(duì)象的Name屬性值。
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Sketch7" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
public partial class MainWindow : Window
{
Employee employee = new Employee() { Name = "Default Name" };
public MainWindow()
{
InitializeComponent();
Binding binding = new Binding();
binding.Source = employee;
binding.Path = new PropertyPath("Name");
BindingOperations.SetBinding(this.InputTextBox, TextBox.TextProperty, binding);
}
private void OutputName_Click(object sender, RoutedEventArgs e)
{
this.OutputTextBox.Text = "My name is"+employee.Name;
}
}
運(yùn)行程序,我們發(fā)現(xiàn),剛開始會(huì)展示設(shè)置的“Default Name”,若改變文本塊的內(nèi)容,則單擊output按鈕后,其對(duì)應(yīng)的文本也會(huì)被改變,說明此時(shí)已經(jīng)實(shí)現(xiàn)了雙向數(shù)據(jù)綁定。當(dāng)然了,并非所有的數(shù)據(jù)綁定都需要在后置代碼中編寫來實(shí)現(xiàn),我們也可以在XAML頁(yè)面使用標(biāo)記擴(kuò)展的功能來聲明Binding對(duì)象實(shí)現(xiàn)數(shù)據(jù)綁定,同樣也是需要指定源和路徑的,我們稍后會(huì)在多種源和路徑的形式中進(jìn)行討論。
總結(jié)一下,在實(shí)現(xiàn)數(shù)據(jù)綁定時(shí),我們需要注意下面的要點(diǎn):
建立綁定需要使用 Binding 對(duì)象。在建立綁定時(shí),需要設(shè)置源和路徑,然后將綁定目標(biāo)綁定到綁定源。目標(biāo)屬性必須為依賴屬性。大多數(shù) UIElement 屬性都是依賴屬性,而大多數(shù)依賴屬性(只讀屬性除外)默認(rèn)支持?jǐn)?shù)據(jù)綁定。 只有從 DependencyObject 派生的類型才能定義依賴項(xiàng)屬性。 所有 UIElement 類型從 DependencyObject 派生。有關(guān)依賴屬性的內(nèi)容我們下一節(jié)描述。綁定源對(duì)象不限于自定義 .NET 對(duì)象。 WPF 數(shù)據(jù)綁定支持 .NET 對(duì)象、XML 或是 XAML 元素對(duì)象形式的數(shù)據(jù)。稍后我們將對(duì)不同類型的數(shù)據(jù)源及其路徑進(jìn)行討論。
5.4數(shù)據(jù)流的方向
如果對(duì)于上面這個(gè)例子,我們希望用戶在文本框的輸入不會(huì)改變到Name的屬性值,只有屬性值的改變會(huì)變更文本框的展示,就需要對(duì)數(shù)據(jù)流的方向進(jìn)行設(shè)置。我們有時(shí)希望應(yīng)用允許用戶更改數(shù)據(jù),然后將該數(shù)據(jù)傳播回源對(duì)象。有時(shí)不希望允許用戶更新源數(shù)據(jù)??梢酝ㄟ^設(shè)置 Binding.Mode 來控制數(shù)據(jù)流。
通過 OneWay 綁定,對(duì)源屬性的更改會(huì)自動(dòng)更新目標(biāo)屬性,但對(duì)目標(biāo)屬性的更改不會(huì)傳播回源屬性。 例如,在上面的例子中, 我們希望用戶在文本框的輸入不會(huì)改變到Name的屬性值,只有屬性值的改變會(huì)變更文本框的展示,可以將Binding.Mode設(shè)置為OneWay。此外,如果無需監(jiān)視目標(biāo)屬性的更改,則使用 OneWay 綁定模式可避免 TwoWay 綁定模式的系統(tǒng)開銷。通過 TwoWay 綁定,更改源屬性或目標(biāo)屬性時(shí)會(huì)自動(dòng)更新另一方,也就是雙向數(shù)據(jù)綁定。 此類型的綁定適用于可編輯窗體或其他完全交互式 UI 方案。 在不設(shè)定Binding.Mode的情況下,大多數(shù)屬性默認(rèn)為 OneWay 綁定,但某些依賴屬性(通常為用戶可編輯控件的屬性,例如 TextBox.Text 和 CheckBox.IsChecked)默認(rèn)為 TwoWay 綁定。OneWayToSource 綁定與 OneWay 綁定相反;當(dāng)目標(biāo)屬性更改時(shí),它會(huì)更新源屬性,反之則不會(huì)。OneTime 會(huì)使源屬性初始化目標(biāo)屬性,但不傳播后續(xù)更改。 如果數(shù)據(jù)發(fā)生更改,則更改不會(huì)在目標(biāo)屬性中反映。如果你想使用源屬性中的某個(gè)值來初始化目標(biāo)屬性,且提前不知道數(shù)據(jù)上下文,則此類型的綁定也有用。 此模式實(shí)質(zhì)上是 OneWay 綁定的一種簡(jiǎn)化形式,它在源值不更改的情況下提供更好的性能。
柚子快報(bào)激活碼778899分享:c# WPF基礎(chǔ)應(yīng)用
參考鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。