C# wpf

學習網址:控件的父類們 - WPF中文網 - 從小白到大佬

控件的父類:

由此我們可以得出結論,控件的父類們(準確的說,應該叫父類的父類的父類),至少有如下幾個類型:

  • DispatcherObject
  • DependencyObject
  • Visual
  • UIElement
  • FrameworkElement

WPF幾乎所有的控件都從上面這五個父類繼承,它們的相互繼承關系,形成了一棵樹。

DispatcherObject類

在UI線程上給你們提供一個中間商Dispatcher(調度員),將Dispatcher放到一個抽象類DispatcherObject,然后我向你保證,我所有的控件都從這個DispatcherObject類繼承,這樣當你們在后臺線程中要訪問控件時,就可以從控件中找到那位中間商Dispatcher,由中間商來完成你要對控件的操作訪問。

從此,DispatcherObject在WPF的世界中,便登上了至高無上的寶座,成為了幾乎所有類型的終極基類。

需要在后臺線程中去操作控件,于是Dispatcher調度員提供了Invoke和BeginInvoke兩個方法,供我們可以安全的訪問UI線程中的控件。

官方解釋:

在 WPF 中,?DispatcherObject?只能由?Dispatcher?它與之關聯的訪問。 例如,后臺線程無法更新與?Dispatcher?UI 線程上關聯的內容Button。 為了使后臺線程訪問該?Content?屬性?Button,后臺線程必須將工作委托給?Dispatcher?與 UI 線程關聯的工作。 這是通過使用?Invoke?或BeginInvoke。?Invoke?是同步的,?BeginInvoke?是異步的。 操作將添加到指定DispatcherPriority位置的隊列Dispatcher中。

namespace HelloWorld
{
? ? /// <summary>
? ? /// MainWindow.xaml 的交互邏輯
? ? /// </summary>
? ? public partial class MainWindow : Window
? ? {
? ? ? ? public MainWindow()
? ? ? ? {
? ? ? ? ? ? InitializeComponent();
?
? ? ? ? ? ? Task.Factory.StartNew(() =>
? ? ? ? ? ? {

//Task.Delay(3000):創建一個表示 3 秒延遲的?Task?對象。它不會阻塞當前線程,而是返回一個表示延遲的異步任務。

//.Wait():阻塞當前線程,直到?Task?完成。在這里,Wait()?會等待?Task.Delay(3000)?的 3 秒延遲完成。

? ? ? ? ? ? ? ? Task.Delay(3000).Wait();
? ? ? ? ? ? ? ? ?//button:前端UI

? ? ? ? ? ? ? ? //在后端想改變前端數據時使用:
? ? ? ? ? ? ? ? button.Dispatcher.Invoke(() =>
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? button.Content = "www.wpfsoft.com";
? ? ? ? ? ? ? ? });
? ? ? ? ? ? });?
? ? ? ? }
? ? }
}

  • 提供方法以檢查 (CheckAccess) 和驗證 (VerifyAccess) 某個線程是否有權訪問對象(派生于 DispatcherObject)。CheckAccess 與 VerifyAccess 的區別在于 CheckAccess 返回一個布爾值,表示當前線程是否有可以使用的對象,而 VerifyAccess 則在線程無權訪問對象的情況下引發異常。

DependencyObject類

控件的屬性不再被直接賦值,而是綁定了另一個”變量“,當這個”變量“發生改變時,控件的屬性也會跟著改變,這樣的屬性也被稱為依賴屬性。

DependencyObject 類表示參與依賴屬性系統的對象。屬性系統的主要功能是計算屬性的值,并提供有關已更改的值的系統通知。 參與屬性系統的另一個類 DependencyProperty。 DependencyProperty 允許將依賴屬性注冊到屬性系統,并提供有關每個依賴屬性的標識和信息,而 DependencyObject 為基類,使對象能夠使用此依賴屬性。
INotifyPropertyChanged 類用于通知UI刷新,注重的僅僅是數據更新后的通知。DependencyObject 類用于給UI添加依賴和附加屬性,注重數據與UI的關聯。如果簡單的數據通知,兩者都可以實現的。

Visual類

Visual類是WPF框架中第三個父類,主要是為 WPF 中的呈現提供支持,其中包括命中測試、坐標轉換和邊界框計算。它位于程序集:PresentationCore.dll庫文件中,它的命名空間:System.Windows.Media。

Visual 類是派生每個 FrameworkElement 對象的基本抽象。 該類還用作在 WPF 中編寫新控件的入口點,在 Win32 應用程序模型中,該類在許多方面可視為窗口句柄 (HWND)。Visual?對象是一個核心 WPF 對象,它的主要作用是提供呈現支持。 用戶界面控件如?Button?和?TextBox)派生自?Visual?類,并使用該類來保存它們的呈現數據。?Visual?對象為以下項提供支持:
輸出顯示:呈現視覺對象的持久、序列化的繪圖內容。
轉換:針對視覺對象執行轉換。
剪裁:為視覺對象提供剪裁區域支持。
命中測試:確定坐標或幾何形狀是否包含在視覺對象的邊界內。
邊框計算:確定視覺對象的邊框。

所有控件都繼承了Visual類,控件在繪制到界面的過程中,涉及到轉換、裁剪、邊框計算等功能,都是使用了Visual父類的功能。

UIElement類

UIElement類繼承了Visual類,在WPF框架中排行老四(第4個基類)。它位于程序集:PresentationCore.dll之中,命名空間:System.Windows。

第一部分 路由事件

UIElement基類定義了大量的路由事件。什么是路由事件?路由事件和xaml的可視化樹概念相關,控件的事件被觸發后,會沿著這棵樹廣播,有兩個方向,要么往樹的根部廣播,要么往樹的枝葉廣播,如果不廣播就是直接事件。

所以,路由事件分為冒泡事件和隧道事件,冒泡,是從觸發源為出發點,依次傳遞到父節點,直到最后的根節點。隧道事件是不管誰是觸發源,都是從根節點觸發,到子節點,直到觸發節點。

從空間上來說,冒泡事件和隧道事件是成對出現的。從時間來說,都是先觸發隧道事件,然后是冒泡事件。從命名來說,隧道事件都是以Preview開頭的事件。

根據命名規則,我們可以大致猜測出一個結果,帶Key的基本都是與鍵盤相關的事件(如按下鍵位、抬起鍵位),帶Mouse的基本都是與鼠標相關的事件(如左鍵單擊、雙擊),帶Stylus的基本都是與觸摸相關的事件,具體用到哪一類型的事件,再詳細查閱一下相關說明文檔即可。

重點:關于這些事件的回調函數,即以On開頭的方法成員,都被聲明成了protected virtual,意思是他們都可以被重載,這使得我們在開發業務時更加方便。

第二部分 依賴屬性

UIElement基類還定義了大量的依賴屬性。前面的章節中,在DependencyObject類中我們簡單提到過依賴屬性。在這里我們以UIElement基類的Visibility屬性為例。

 
public Visibility Visibility { get; set; }
public static readonly DependencyProperty VisibilityProperty;

上面有兩個成員,Visibility是普通的屬性成員,VisibilityProperty是WPF的依賴屬性成員,以Property結尾的字樣作為WPF的依賴屬性命名規則。而這兩個成員合起來,才能被稱為一個完整的依賴屬性。這個Visibility 屬性表示設置或獲取控件的可見性。當我們要設置控件的可見性時,只需要如下設置即可。

 
<TextBlock Text="WPF中文網"
Visibility="Visible"
FontSize="48"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>

Visibility實際上是一個枚舉,它包含3個值,分別是Visible、Hidden、Collapsed。其含義分別是顯示、隱藏、徹底隱藏(不占布局位置)。

Visibility?狀態會影響該元素的所有輸入處理。 不可見的元素不會參與命中測試,也不會接收輸入事件,即使鼠標位于元素可見時所在的邊界上也是如此。

但是在這一節中,我們只是探討UIElement基類提供了哪些方面的屬性,并不詳細探討依賴屬性,所以下面我們把目光聚焦到UIElement基類的常用屬性上。另外由于WPF中幾乎所有控件都繼承了這個基類,意思就是說所有的控件都有這些屬性可以使用。下面我在描述的時候將采用“控件”兩字來解釋一些技術細節。

Uid屬性:獲取或設置控件的唯一標識符,像人們的身份證一樣。這個值默認是string.Empty。

Visibility屬性:獲取或設置控件的可見性。默認是Visible。

ClipToBounds屬性:如果該值為true,表示進行裁剪,以適配它的父控件。比如有時候我們外面有一個Panel,里面的控件尺寸太大,勢必會“撐破”外面的父控件,為了布局美觀,只好削足適履。

Clip屬性:用于剪裁區域大小的幾何圖形。需要注意的是,這個屬性和上面的ClipToBounds屬性是有區別的。ClipToBounds是裁剪控件自身,Clip是裁剪控件里面的內容。比如Image圖像控件,我們在顯示一張圖時,就可以運用Clip進行裁剪后顯示,通常在顯示用戶頭像時裁剪成圓形時使用。如下所示

<Image?
? Source="sampleImages\Waterlilies.jpg"?
? Width="200" Height="150" HorizontalAlignment="Left">
? <Image.Clip>
? ? <EllipseGeometry
? ? ? RadiusX="100"
? ? ? RadiusY="75"
? ? ? Center="100,75"/>
? </Image.Clip>
</Image>
?

SnapsToDevicePixels屬性:如果該值為true,表示控件的呈現是否應使用特定于設備的像素設置。意思是開啟后可以最大限度的防鋸齒效果,默認為false。

IsFocused屬性:這是一個只讀屬性,表示當前控件是否有焦點。

IsEnabled屬性:如果該值為true,表示禁用控件,反之啟用控件。

IsHitTestVisible屬性:獲取或設置一個值,該值聲明是否可以返回此元素作為其呈現內容的某些部分的點擊測試結果。

IsVisible屬性:這是一個只讀屬性,表示當前控件是否顯示。

Focusable屬性:如果該值為true,表示控件可以得到焦點,大部份內容控件都默認可以獲得焦點。

IsKeyboardFocused屬性:表示該控件是否具有鍵盤焦點。

IsMouseOver屬性:表示鼠標是否在控件上面。通常在設計控件的樣式(Style)時會用到。

IsStylusOver屬性:表示觸筆指針是否在控件的上方。

IsSealed屬性:表示當前類型是否為只讀類。

Opacity屬性:設置控件的透明度,取值范圍是0-1之間的double值。

OpacityMask屬性:設置一個畫筆,作為控件的蒙板。比如我們給一張圖片設置一個掩碼,就可以使用ImageBrush這種圖片畫筆來實現。

AllowDrop屬性:表示控件是否允許拖拽操作。

RenderTransform屬性:(非常重要)如果要設置控件的移動、縮放、旋轉,需要這此屬性進行設置。

總結

通過上述的代碼分析,我們大致可以得出以下結論,UIElement基類為我們提供了一系列的鼠標、鍵盤和觸摸事件,并提供了一些常用的依賴屬性。它可以呈現繼承它的所有控件,為控件布局時調整位置和大小,響應用戶的輸入,引發一系列的路由事件,并繼承了IAnimatable動畫接口,用于支持動畫的某些方面。

FrameworkElement類

它是WPF控件的眾多父類中最核心的基類,從這里開始,繼承樹開始分支,分別是Shape圖形類、Control控件類和Panel布局類三個方向。

FrameworkElement類本質上也是提供了一系列屬性、方法和事件。同時又擴展 UIElement 并添加了以下功能:

官方文檔

1.布局系統定義:?FrameworkElement?為中?UIElement定義為虛擬成員的某些方法提供特定的 WPF 框架級實現。 最值得注意的是,?FrameworkElement?會密封某些 WPF 核心級布局替代,并改為提供派生類應替代的 WPF 框架級別的等效項。 例如,密封但?FrameworkElementArrangeCore?提供?ArrangeOverride。 這些更改反映了這樣一個事實,即在 WPF 框架級別,有一個可以呈現任何?FrameworkElement?派生類的完整布局系統。 在 WPF 核心級別,將構建基于 WPF 的常規布局解決方案的某些成員已就位,但未定義布局系統的實際引擎。
2.邏輯樹:?常規 WPF 編程模型通常以元素樹的方式表示。 支持將元素樹表示為邏輯樹,以及支持在標記中定義該樹的支持是在 級別實現的?FrameworkElement?。 但請注意,?FrameworkElement?故意不定義內容模型,并將該責任留給派生類。
3.對象生存期事件:?了解何時初始化元素 (調用構造函數) 或首次將元素加載到邏輯樹中時,這通常很有用。?FrameworkElement?定義多個與對象生存期相關的事件,這些事件為涉及元素的代碼隱藏操作(例如添加更多子元素)提供有用的掛鉤。
4.支持數據綁定和動態資源引用:?對數據綁定和資源的屬性級支持由?DependencyProperty?類實現,并體現在屬性系統中,但解析存儲為?Expression?(數據綁定和動態資源的編程構造) 中存儲的成員值的能力由?FrameworkElement實現。
5.風格:FrameworkElement?定義?Style?屬性。 但是,?FrameworkElement?尚未定義對模板的支持或支持修飾器。 這些功能由控件類(如 和?ContentControl)Control引入。
6.更多動畫支持:?某些動畫支持已在 WPF 核心級別定義,但?FrameworkElement?通過實現?BeginStoryboard?和相關成員擴展了此支持。

屬性分析

1.LayoutTransform 屬性:獲取或設置在執行布局時應應用于此元素的圖形轉換。這個屬性與UIElement類中的RenderTransform屬性有相似之處,所以我們在此將兩者進行對比說明一下。兩個屬性都是Transform類型,而Transform是一個抽象類,這個類可以實現控件在平面中的各種轉換,包括

  • 旋轉 (System.Windows.Media.RotateTransform)
  • 縮放 (System.Windows.Media.ScaleTransform)、
  • 傾斜 (System.Windows.Media.SkewTransform) 、
  • 平移 (System.Windows.Media.TranslateTransform)。

雖然兩個屬性都可以達到控件的變換效果,但是兩者還是有區別的。LayoutTransform屬性是在控件布局之前對控件進行變換,而RenderTransform屬性是在布局結束后執行控件的變換,LayoutTransform開銷比RenderTransform要大,所以,盡量使用RenderTransform屬性去實現控件的變換。(我們會在后面專門探討控件的變換)

2.Width屬性:這是表示控件的寬度。與之相關的還有以下幾個屬性。

  • ActualWidth:獲取此元素的呈現寬度。只讀屬性。
  • MaxWidth:獲取或設置一個控件的最大寬度。
  • MinWidth:獲取或設置一個控件的最小寬度。

3.Height屬性:這是表示控件的高度,與之相關的還有以下幾個屬性。

  • ActualHeight:獲取此元素的呈現高度。只讀屬性。
  • MaxHeight:獲取或設置一個控件的最大高度。
  • MinHeight:獲取或設置一個控件的最小高度。

4.Tag屬性:這個屬性非常重要,它是object類型,意味著可以保存任意類型的對象值。它就像FrameworkElement類身上的一個小口袋,但確能容納萬物。我們通常會將一些與控件相關的數據臨時存放在Tag屬性中,當把控件作為參數傳遞時,小口袋里面的對象也隨之傳遞過去了。

5.Name屬性:獲取或設置控件的標識名稱。在同一個窗體、頁、用戶控件中,Name標識是唯一的。設置了控件的名稱后,我們就可以在后端代碼直接以這個標識去引用控件。

6.Margin屬性:獲取或設置控件的外邊距。

Padding屬性說明

與Margin相對應的是Padding,表示設置控件的內邊距。但是這個屬性并不在FrameworkElement中,而在Control類中,從本節第一張圖所示,說明只有內容控件才具有Padding,而Shape和Panel是沒有Padding屬性的。

7.HorizontalAlignment屬性:設置控件的水平對齊方式。這個對齊方式是相對于父元素而言的,比如我們有一個Button控件,在外面還包裹了一層Grid控件,那么,設置Button控件的HorizontalAlignment屬性,可以將Button控件分別顯示在Grid控件的左邊、中間、右邊三個位置。

8.VerticalAlignment屬性:設置控件的垂直對齊方式。與HorizontalAlignment屬性類似,只是對方的方向不同,可以設置控件在垂直方向上是居于頂部、中間、還是底部三個位置。

總結:上述兩個屬性的值都是枚舉型,它們都有一個共同的值,那就是stretch,表示是拉伸的方式填充父元素的布局。

9.ToolTip屬性:獲取或設置用戶界面 (UI) 中為此元素顯示的工具提示對象。指鼠標移到控件上方時顯示的提示內容,它是一個object類型,意味著可以顯示任意布局外觀。

10.Parent屬性:獲取此元素的邏輯父元素。它是一個只讀屬性。

接下來,我們將介紹幾個比較重要的屬性,這些屬性是WPF框架中非常核心的知識概念.

WPF樣式(Style)

11.Style屬性:獲取或設置此元素呈現時所使用的樣式。與Style相關的還有一個屬性,叫FocusVisualStyle,顧名思義,控件在獲得焦點時的樣式。

WPF資源(ResourceDictionary)

什么是資源?資源,也就是資源字典,也就是ResourceDictionary類,它提供一個哈希表/字典實現,其中包含組件所使用的 WPF 資源以及 WPF 應用程序的其他元素。我們可以把WPF的控件、窗體、Application應用所用到的一切資源都放在其中,將多個ResourceDictionary元素合并起來形成一個ResourceDictionary元素(ResourceDictionary也是一個隱式集合)。所以FrameworkElement類設計一個資源屬性。

12.Resources 屬性:獲取或設置本地定義的資源字典。關于Resources資源我們會專門拿一章節來探討)

WPF的數據上下文(DataContext)

假定我們有一個View窗體,窗體有一個TextBox控件;又假如我們還有一個ViewModel實體,這個實體中有一個叫Name的屬性。如果我們要將TextBox控件的Text屬性和ViewModel實體的Name屬性成功的建立綁定關系,必備的條件是什么?

首先,由于View窗體繼承于FrameworkElement類,所以每個窗體(或控件)都有一個叫DataContext的數據上下文屬性。所以必備的條件是:ViewModel實體必須先賦值給View窗體的DataContext,ViewModel的Name屬性才能綁定到TextBox控件的Text屬性。換言之,領導之間要先搭好橋,下屬和下屬才好配合工作。這就是DataContext的概念和用途。

13.DataContext屬性:獲取或設置元素參與數據綁定時的數據上下文。

14.ContextMenu屬性:設置與獲取控件的上下文菜單 ,就是鼠標在控件上右鍵時彈出來的菜單。

15.Cursor屬性:獲取或設置在鼠標指針位于此元素上時顯示的光標。

事件分析

FrameworkElement類提供了12個事件,一般比較常用的是:Initialized、Loaded、Unloaded、SizeChanged等事件。

1.FindName(String):表示查找某個元素。比如我們在窗體中要查找某個控件。

2.FindResource(Object):查找某個資源。如果在調用對象上找不到該資源,則接下來搜索邏輯樹中的父元素,然后搜索應用程序、主題,最后搜索系統資源。實在找不到就拋出異常。

3.TryFindResource(Object):嘗試去找某個資源。建議使用這個方法。

4.RegisterName (string , object );注冊控件的名稱到父控件上。

5.SetBinding(DependencyProperty, BindingBase)和SetBinding(DependencyProperty, String),這兩個成員都和綁定相關,我們將在后面做專題介紹。

布局控件概述

控件名稱布局方式
Grid網格,根據自定義行和列來設置控件的布局
StackPanel棧式面板,包含的元素在豎直或水平方向排成一條直線
WrapPanel自動折行面板,包含的元素在排滿一行后,自動換行
DockPanel泊靠式面板,內部的元素可以選擇泊靠方向
UniformGrid網格,UniformGrid就是Grid的簡化版,每個單元格的大小相同。
Canvas畫布,內部元素根據像素為單位絕對坐標進行定位
Border裝飾的控件,此控件用于繪制邊框及背景,在Border中只能有一個子控件

Panel基類

Panel其實是一個抽象類,不可以實例化,WPF所有的布局控件都從Panel繼承而來

它有一個Background屬性,意味著所有的布局控件都可以設置背景顏色。另外,它還有一個Children屬性,這是一個集合屬性,也就是說,所有的布局控件都可以添加多個子元素。這一點從它繼承的IAddChild接口也能得到印證。

Panel提供了GetZIndex和SetZIndex方法成員,分別表示獲取某個元素的ZIndex順序和設置某個元素的ZIndex順序。

什么是ZIndex?這是Panel提供的一個附加屬性。假如一個單行單列的Grid布局控件中有兩個Button,正常情況下,這兩個Button都會以撐滿Grid的方式呈現在Grid中,那么,到底哪一個Button在上面,哪一個Button在下面呢?就看這兩個Button的Panel.ZIndex附加屬性的值,值越大越在上面,而值較小的那個Button將被上面的Button遮蓋,從而在視覺上,用戶只能看到一個Button。

附加屬性

附加屬性的一個用途是允許子元素存儲實際上由父元素定義的屬性的唯一值。 此功能的一項應用是讓子元素通知父級它們希望如何在用戶界面 (UI) 中呈現,這對應用程序布局非常有用。
<Grid >
<Button Content="WPF中文網1" Panel.ZIndex="1" Margin="20 40 60 80" Padding="50" />
<Button Content="WPF中文網2" Panel.ZIndex="0" Margin="20 40 60 80" Padding="50" />
</Grid>

WPF 提供了一套全面的派生 Panel 實現,可實現許多復雜的布局。這里有一個非常非常需要注意的事項,那就是Panel的Background屬性。有時候我們希望在布局控件上實現鼠標點擊事件的獲取,請記得一定要給Background屬性設置一個顏色值,如果不希望有具體的顏色,那就設置成Transparent?。不然,您會踩坑的!因為布局控件的Background屬性沒有值時,是不能引發鼠標相關事件的

只要繼承于UIElement的類(或控件),都可以添加到Panel或Panel子類的Children中,從而在前端呈現出來

一個Panel 的呈現就是測量和排列子控件,然后在屏幕上繪制它們。所以在布局的過程中會經過一系列的計算,那么子控件越多,執行的計算次數就越多,則性能就會變差。如果不需要進行復雜的布局,則盡量少用復雜布局控件(如 Grid和自定義復雜的Panel);如果能簡單布局實現就盡量使用構造相對簡單的布局(如 Canvas、UniformGrid等),這種布局可帶來更好的性能。 如果有可能,我們應盡量避免調用 UpdateLayout方法。

布局系統為Panel中的每個子控件完成兩個處理過程:測量處理過程(Measure)和排列處理過程(Arrange)。每個子?Panel?均提供自己的?MeasureOverride?和?ArrangeOverride?方法,以實現自己特定的布局行為。

Grid控件(網格布局)

Grid有兩個非常關鍵的屬性ColumnDefinitions和RowDefinitions,分別表示列的數量集合和行的數量集合。ColumnDefinitions集合中的元素類型是ColumnDefinition類,RowDefinitions集合中元素類型是RowDefinition類。默認的Gridr控件沒有定義行數和列數,也就是說,Grid默認情況下,行數和列數都等于1,那么它就只有一個單元格。

//一行兩列

<Grid >
? ? <Grid.ColumnDefinitions>
? ? ? ? <ColumnDefinition/>
? ? ? ? <ColumnDefinition/>

? ? </Grid.ColumnDefinitions>
? ? <Button Grid.Column="0" Content="WPF中文網1" Panel.ZIndex="1" Margin="20" Padding="50" />
? ? <Button Grid.Column="1" Content="WPF中文網2" Panel.ZIndex="0" Margin="20" Padding="50" />
</Grid>

//兩行一列

<Grid>
? ? ? ? <Grid.RowDefinitions>
? ? ? ? ? ? <RowDefinition/>
? ? ? ? ? ? <RowDefinition/>

? ? ? ? </Grid.RowDefinitions>
? ? ? ? <Button Grid.Row="0" Content="WPF中文網1" Panel.ZIndex="1" Margin="20" Padding="50" />
? ? ? ? <Button Grid.Row="1" Content="WPF中文網2" Panel.ZIndex="0" Margin="20" Padding="50" />
? ? </Grid>

跨列排列:

<Grid>
? ? <Grid.RowDefinitions>
? ? ? ? <RowDefinition/>
? ? ? ? <RowDefinition/>
? ? </Grid.RowDefinitions>
? ? <Grid.ColumnDefinitions>
? ? ? ? <ColumnDefinition/>
? ? ? ? <ColumnDefinition/>
? ? </Grid.ColumnDefinitions>
? ? <Button Grid.Row="0" Grid.Column="0" Content="WPF中文網1" Panel.ZIndex="1" Margin="20" Grid.ColumnSpan="2"/>//跨2列
? ? <Button Grid.Row="1" Grid.Column="0" Content="WPF中文網3" Panel.ZIndex="1" Margin="20" />
? ? <Button Grid.Row="1" Grid.Column="1" Content="WPF中文網4" Panel.ZIndex="0" Margin="20" />
</Grid>

固定列寬:

我們只需要設置第一行ColumnDefinition的Width屬性,讓其寬度固定為120像素,那么第二列的寬度等于Grid的寬度減去120像素,其內部的Button寬度也隨之自適應。這就是WPF布局自適應的好處。

<Grid>
? ? <Grid.RowDefinitions>
? ? ? ? <RowDefinition/>
? ? ? ? <RowDefinition/>
? ? </Grid.RowDefinitions>
? ? <Grid.ColumnDefinitions>
? ? ? ? <ColumnDefinition Width="120"/>
? ? ? ? <ColumnDefinition/>
? ? </Grid.ColumnDefinitions>
? ? <Button Grid.Row="0" Grid.Column="0" Content="WPF中文網1" Panel.ZIndex="1" Margin="20" />
? ? <Button Grid.Row="0" Grid.Column="1" Content="WPF中文網2" Panel.ZIndex="0" Margin="20" />
? ? <Button Grid.Row="1" Grid.Column="0" Content="WPF中文網3" Panel.ZIndex="1" Margin="20" />
? ? <Button Grid.Row="1" Grid.Column="1" Content="WPF中文網4" Panel.ZIndex="0" Margin="20" />
</Grid>

調整行高和列寬

Grid控件的行高和列寬的設置十分豐富,了解它們的用法,有助于設計出更出色的布局。

名稱說明
絕對設置尺寸使用設備無關單位準確地設置尺寸,就是給一個實際的數字,但通常將此值指定為整數(像素)。如:<ColumnDefinition Width="100"></ColumnDefinition>
自動設置尺寸值為Auto,實際作用就是取實際控件所需的最小值,每行和每列的尺寸剛好滿足需要,這是最有用的尺寸設置方式。如:<ColumnDefinition Width="Auto"></ColumnDefinition>
按比例設置設置尺寸按比例將空間分割到一組行和列中。這是對所有行和列的標準設置。通常值為*或N*,實際作用就是取盡可能大的值,當某一列或行被定義為*則是盡可能大,當出現多列或行被定義為*則是代表幾者之間按比例方設置尺寸。如:<ColumnDefinition Width="*"></ColumnDefinition>

指定權重,即第2列的寬度是第1列的兩倍

<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="2*"></RowDefinition>

Grid顯示網格線

<Grid ShowGridLines="True" Margin="5">

</Grid>

Border?是一個常用的控件,用于在界面上繪制一個矩形邊框,通常用于裝飾或分組其他控件。Border?控件可以包含一個子元素,并在該子元素周圍繪制邊框。

<Grid Margin="5">
? ? <Grid.RowDefinitions>
? ? ? ? <RowDefinition/>
? ? ? ? <RowDefinition/>
? ? </Grid.RowDefinitions>
? ? <Grid.ColumnDefinitions>
? ? ? ? <ColumnDefinition Width="120"/>
? ? ? ? <ColumnDefinition/>
? ? </Grid.ColumnDefinitions>
? ? <Border Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="2" BorderBrush="Gray" BorderThickness="1"/>
? ? <Border Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" BorderBrush="Gray" BorderThickness="0 0 0 1"/>
? ? <Border Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" BorderBrush="Gray" BorderThickness="0 0 1 0"/>
? ? <Button Grid.Row="0" Grid.Column="0" Content="WPF中文網1" Panel.ZIndex="1" Margin="20" />
? ? <Button Grid.Row="0" Grid.Column="1" Content="WPF中文網2" Panel.ZIndex="0" Margin="20" />
? ? <Button Grid.Row="1" Grid.Column="0" Content="WPF中文網3" Panel.ZIndex="1" Margin="20" />
? ? <Button Grid.Row="1" Grid.Column="1" Content="WPF中文網4" Panel.ZIndex="0" Margin="20" />
</Grid>

我們在Grid內部增加了3個Border,第一個Border用來顯示外邊框,第二個Border顯示中間的橫線,第三個Border顯示中間的豎線,這時所用的知識點幾乎都是Grid的跨行和跨列屬性,另外還有邊框顏色刷子BorderBrush和邊框厚度BorderThickness。

*其他布局(待學)

Control基類

通常用于展示程序的數據或獲取用戶輸入的數據,我們可以將這一類型的控件稱為內容控件或數據控Control類雖然可以實例化,但是在界面上是不會有任何顯示的。只有那些繼承了Control的子類(控件)才會在界面上顯示,Control類提供了一個控件模板(ControlTemplate),而幾乎所有的子類都對這個ControlTemplate進行了各自的實現。

Control的Template定義了控件的外觀,Control類的Template屬性是ControlTemplate類型的。

<Window x:Class="HelloWorld.MainWindow"
? ? ? ? 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:HelloWorld"
? ? ? ? mc:Ignorable="d"
? ? ? ? Title="HelloWorld - www.wpfsoft.com" Height="350" Width="500">
? ? <Control Margin="10">
? ? ? ? <Control.Template>
? ? ? ? ? ? <ControlTemplate TargetType="Control">
? ? ? ? ? ? ? ? <Border Background="LightBlue">
? ? ? ? ? ? ? ? ? ? <TextBlock Text="WPF中文網" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
? ? ? ? ? ? ? ? </Border>
? ? ? ? ? ? </ControlTemplate>
? ? ? ? </Control.Template>
? ? </Control>
</Window>

事件

在這一小節里,您只要能明白Template的概念就行了。除了這個屬性,Control類還提供了兩個事件,它們分別是PreviewMouseDoubleClick和MouseDoubleClick。

事件名稱說明
PreviewMouseDoubleClick表示鼠標雙擊或多次單擊時觸發的事件
MouseDoubleClick表示鼠標雙擊或多次單擊時觸發的事件

以Preview開頭的事件叫隧道事件或預覽事件,而MouseDoubleClick沒有以Preview開頭,所以它叫冒泡事件。

*其他(待學)

數據綁定

數據綁定是在應用 UI 與其顯示的數據之間建立連接的過程。 如果綁定具有正確的設置,并且數據提供適當的通知,則在數據更改其值時,綁定到該數據的元素會自動反映更改。 數據綁定還意味著,如果元素中數據的外部表示形式發生更改,則基礎數據可以自動進行更新以反映更改。

這就是數據綁定!

圖的左邊是一個DependencyObject對象,表明它是一個依賴對象。那么,WPF控件是不是一個DependencyObject對象?是的,因為WPF所有的控件都繼承了DependencyObject基類。

圖的右邊是一個普通的對象,所以這里標注成object類型。右邊的對象表示綁定的數據源——也就是一個ViewModel。

DataContext數據上下文

DataContext是FrameworkElement基類的一個屬性。其含義:獲取或設置元素參與數據綁定時的數據上下文。通常情況下,我們把它設計成一個class——也就是所謂的ViewModel。

View負責數據的輸入與輸出;ViewModel負責業務邏輯;Model則表示程序中具體要處理的數據。所以,Model將作為屬性存在于ViewModel中,而Model最終是要顯示在Ul界面(View)上的,怎么辦呢?將ViewModel賦值給View的DataContext(數據上下文)屬性,View就可以引用ViewModel中的那些Model了。

總結:Model在ViewModel中,ViewModel在View的DataContext中,View引用Model。

WPF所有的控件(包括Window窗體)都有DataContext屬性,因為它們都繼承于FrameworkElement基類。

通常一個Window窗體中有很多控件,我們只需要給Window的DataContext賦值一個ViewModel,窗體中其它的控件的DataContext會共享Window的DataContext。

Model類

public class Person
{
? ? public string Name { get; set; }
? ? public int Age { get; set; }
? ? public string Address { get; set; }
?
}

ViewModel類

public class MainViewModel
{
? ? public Person Person { get; set; }
?
? ? public MainViewModel()
? ? {
? ? ? ? Person = new Person
? ? ? ? {
? ? ? ? ? ? Name = "張三",
? ? ? ? ? ? Age = 50,
? ? ? ? ? ? Address = "居無定所",
? ? ? ? };
? ? }
}

DataContext屬性賦值

public partial class MainWindow : Window
{
? ? public MainWindow()
? ? {
? ? ? ? InitializeComponent();
?
? ? ? ? this.DataContext = new MainViewModel();
? ? } ? ? ? ?
}

我們給MainWindow主窗體的DataContext賦值了一個叫MainViewModel的視圖模型。而MainViewModel中有一個叫Person的屬性,它就代表了程序運行中要處理的數據實體。

現在MainWindow的DataContext(數據上下文)有了一個對象后,我們怎么將這個Person屬性顯示到前端呢,這需要使用Binding——數據綁定。

Binding(綁定)

Binding類架起了控件和ViewModel之間的橋梁,它就像一個媒婆,指示了哪個控件的哪個屬性與哪個ViewModel類的哪個屬性建立綁定關系。提供對綁定定義的高級訪問,該綁定連接綁定目標對象(通常為 WPF 元素)的屬性和任何數據源(例如數據庫、XML 文件,或包含數據的任何對象)。

第一種數據源

也就是ViewModel中的Model。在寫法上直接如下所示:

Text="{Binding Person.Name}"

這里實例化了一個Binding對象,后面緊跟的Person.Name表示一個Path路徑,指的是當前的DataContext中那個ViewModel對象的Person.Name,注意看,Binding的有一個帶參數的構造函數:public Binding(string path);實際上,就是將Person.Name路徑傳給了path形參。

第二種數據源

指明某個具體的數據源對象及對象的屬性。這種綁定方式要用了Binding類的Source屬性和Path屬性。通常寫法如下:

Text="{Binding Source={StaticResource RedBrush},Path=Color}"

在這里,Source屬性表示數據源對象,它是一個靜態資源對象,Path=Color表示要綁定這個靜態資源對象的Color屬性。我們已經提前在資源里定義好了這個資源對象。資源對象的實例名叫RedBrush,它確實也有一個叫Color的屬性。

<Window.Resources>
? ? <SolidColorBrush x:Key="RedBrush" Color="Red"/>
</Window.Resources>

這樣綁定的效果如下圖所示。

看起來Color=Red,實則是一個代表顏色的16進制字符串。

第三種數據源

利用ElementName屬性指明另一個控件作為數據源,這里仍然要用到Path來指定另一個控件的某個屬性路徑。

<StackPanel x:Name="panel" VerticalAlignment="Center" Margin="100,0">
? ? <TextBlock Margin="5">
? ? ? ? <Run Text="Source示例:"/>
? ? ? ? <Run Text="{Binding Source={StaticResource RedBrush},Path=Color}"/>
? ? </TextBlock>
? ? <TextBlock Margin="5">
? ? ? ? <Run Text="ElementName示例:"/>
? ? ? ? <Run Text="{Binding ElementName=panel,Path=Margin}"/>
? ? </TextBlock>
</StackPanel>

通過Binding類的ElementName去指定當前XAML中的另一個StackPanel控件,并綁定其Margin屬性,這樣,TextBlock就顯示了StackPanel控件的Margin屬性值。

第四種數據源

利用RelativeSource屬性綁定一個相對的數據源。這種綁定方式也經常使用,且實用價值很高,作為開發者,一定要掌握它的用法。

<StackPanel x:Name="panel" VerticalAlignment="Center" Margin="80,0">
? ? <TextBlock Margin="5">
? ? ? ? <Run Text="Source示例:"/>
? ? ? ? <Run Text="{Binding Source={StaticResource RedBrush},Path=Color}"/>
? ? </TextBlock>
? ? <TextBlock Margin="5">
? ? ? ? <Run Text="ElementName示例:"/>
? ? ? ? <Run Text="{Binding ElementName=panel,Path=Margin}"/>
? ? </TextBlock>
? ? <TextBlock Margin="5">
? ? ? ? <Run Text="RelativeSource示例:"/>
? ? ? ? <Run Text="{Binding RelativeSource={RelativeSource Mode=Self},Path=Foreground}"/>
? ? ? ? <Run Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=StackPanel},Path=Margin}"/>
? ? </TextBlock> ? ?
</StackPanel>

RelativeSource類有3個重要的屬性,它們分別是Mode、AncestorType和AncestorLevel。

Mode:表示尋找相對數據源的模式,一共有4種模式

模式說明
PreviousData允許在當前顯示的數據項列表中綁定上一個數據項(不是包含數據項的控件)。
TemplatedParent引用應用了模板的元素,其中此模板中存在數據綁定元素。
Self引用正在其上設置綁定的元素,并允許你將該元素的一個屬性綁定到同一元素的其他屬性上。
FindAncestor引用數據綁定元素的父鏈中的上級。 這可用于綁定到特定類型的上級或其子類。

在上面的例子中,我們演示了Self(自身控件)和FindAncestor(找上級控件)兩種模式。

AncestorType:當Mode=FindAncestor時,這時就要指示要找的這個上級是什么類型,AncestorType用來表示上級的類型。

AncestorLevel:獲取或設置要查找的上級級別。 使用 1 指示最靠近綁定目標元素的項。

Text="{Binding RelativeSource={RelativeSource Mode=Self},Path=Foreground}"

表示將自己的前景色顯示到Text屬性上。

Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=StackPanel},Path=Margin}"

表示從當前控件開始找上級,一個類型為StackPanel的控件,并把這個StackPanel控件的Margin顯示到當前控件的Text屬性上。

Binding的綁定模式

當一個實體的屬性綁定到控件的屬性之后,還需要指明這兩者之間的綁定關系。這個就是Binding類的Mode屬性,Mode屬性是一個枚舉類型。它有如下幾個情況。

枚舉值說明
TwoWay雙向綁定,即導致更改源屬性或目標屬性時自動更新另一方。
OneWay單向綁定,在更改綁定源(源)時更新綁定目標(目標)。
OneTime一次綁定,在應用程序啟動或數據上下文更改時,更新綁定目標。
OneWayToSource在目標屬性更改時,更新源屬性。
Default默認綁定,文本框的默認綁定是雙向的,而其他大多數屬性默認為單向綁定。

這里面常用的是OneWay和TwoWay。如果是TwoWay(雙向綁定),意味著前端控件的屬性改變時,后端的Model也跟著改變,反之亦然。就拿前端改變去影響后端的Model值來說,這里會多出來一個概念——改變時機。

其實就是如果前端的值發生改變,后端的值在什么時候跟著改變。它由Binding類的UpdateSourceTrigger屬性的值決定 。這個屬性也是一個枚舉類型。

枚舉值說明
Default采用控件各自的UpdateSourceTrigger默認值。
PropertyChanged每當綁定目標屬性發生更改時,都會更新綁定源。
LostFocus每當綁定目標元素失去焦點時,都會更新綁定源。
Explicit僅在調用 System.Windows.Data.BindingExpression.UpdateSource 方法時更新綁定源。

TextBox.Text 屬性的默認值為 LostFocus,我們經常會把TextBox的UpdateSourceTrigger改成PropertyChanged,即文本框在輸入內容時,實時的更新后端的Model屬性值。

前端屬性值發生改變后,由UpdateSourceTrigger決定什么時候更新后端的Model屬性值,但是,后端那些Model的屬性值發生改變后,前端什么時候跟著改變?需不需要做特殊的處理?

答案是需要!如果Model中的那些屬性沒有實現屬性通知,就算前后端成功的建立了綁定關系,后端Model屬性值改變時,前端的顯示是沒有變化的,如果要實時跟著變化,則需要掌握WPF的INotifyPropertyChanged接口以及屬性通知的相關知識點。

INotifyPropertyChanged接口

通知客戶端屬性值已更改。

public interface INotifyPropertyChanged
{
? ? event PropertyChangedEventHandler PropertyChanged;
}

這個接口只有一個PropertyChanged事件,該事件專門用來觸發屬性更改通知。通常情況下,我們會單獨編寫一個服務類(例如ObservableObject),以實現INotifyPropertyChanged接口的業務。這樣做的好處是,將來的ViewModel、Model都可以繼承這個ObservableObject,從而調用屬性通知接口。

一、實現INotifyPropertyChanged接口

public class ObservableObject : INotifyPropertyChanged
{public event PropertyChangedEventHandler PropertyChanged;public void RaisePropertyChanged([CallerMemberName] string propertyName = ""){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}
}

使用了CallerMemberName特性后,就不必再傳入屬性名字符串。

接下來,我們來編寫一個ViewModel和一個Model,讓它們都繼承這個屬性通知基類。

Person實體

public class Person : ObservableObject
{
? ? private string name;
? ? public string Name
? ? {
? ? ? ? get { return name; }
? ? ? ? set { name = value;RaisePropertyChanged(); }
? ? }
?
? ? private int age;
? ? public int Age
? ? {
? ? ? ? get { return age; }
? ? ? ? set { age = value; RaisePropertyChanged(); }
? ? }
?
? ? private string address;
? ? public string Address
? ? {
? ? ? ? get { return address; }
? ? ? ? set { address = value; RaisePropertyChanged(); }
? ? }
}

MainViewModel實體

public class MainViewModel : ObservableObject
{
? ? private Person person;
? ? public Person Person
? ? {
? ? ? ? get { return person; }
? ? ? ? set { person = value; RaisePropertyChanged(); }
? ? }
?
? ? public MainViewModel()
? ? {
? ? ? ? person = new Person
? ? ? ? {
? ? ? ? ? ? Name = "張三",
? ? ? ? ? ? Age = 50,
? ? ? ? ? ? Address = "居無定所",
? ? ? ? };
? ? }
}

?<StackPanel Orientation="Horizontal">
? ? ? ? ? ? <TextBlock Text="姓名:" Margin="5"/>
? ? ? ? ? ? <TextBox Text="{Binding Person.Name,UpdateSourceTrigger=PropertyChanged}" Width="200" Height="25"/>
? ? ? ? </StackPanel>

除了INotifyPropertyChanged接口可以實現屬性通知,還有一個接口也可以實現屬性通知,它就是INotifyCollectionChanged。它的作用是:當添加和刪除項或清除整個列表時,向偵聽器通知動態更改。也就是說,它是專門來解決集合的元素數量發生變化時的通知問題的。我們在下一節來演示它的用法。

ObservableCollection泛型集合

表示一個動態數據集合,它可在添加、刪除項目或刷新整個列表時提供通知。

?<ListView ItemsSource="{Binding Persons}" SelectedItem="{Binding Person}">
? ? ? ? ? ? <ListView.View>
? ? ? ? ? ? ? ? <GridView>
? ? ? ? ? ? ? ? ? ? <GridViewColumn Header="姓名" DisplayMemberBinding="{Binding Name}" Width="60"/>
? ? ? ? ? ? ? ? ? ? <GridViewColumn Header="年齡" DisplayMemberBinding="{Binding Age}" Width="auto"/>
? ? ? ? ? ? ? ? ? ? <GridViewColumn Header="地址" DisplayMemberBinding="{Binding Address}" Width="auto"/>
? ? ? ? ? ? ? ? </GridView>
? ? ? ? ? ? </ListView.View>
? ? ? ? </ListView>

?public class MainViewModel : ObservableObject
? ? {
? ? ? ? private Person person;
? ? ? ? public Person Person
? ? ? ? {
? ? ? ? ? ? get { return person; }
? ? ? ? ? ? set { person = value; RaisePropertyChanged(); }
? ? ? ? }
?
? ? ? ? public ObservableCollection<Person> Persons { get; set; } = new ObservableCollection<Person>();
? ? ? ? public MainViewModel()
? ? ? ? {
? ? ? ? }
? ? }

ValidationRule驗證規則

ValidationRule是一個抽象類,提供創建自定義規則的一個方式,旨在檢查用戶輸入的有效性。所以,我們要驗證前端輸入的各項數據的有效性時,需要自己定義各自的驗證規則。

在數據綁定時,Binding類有一個ValidationRules屬性,這個屬性專門用來存放開發者自定義的驗證規則。

例如,我們假定用戶名的長度必須在1-10個字符之間,且用戶的年齡在1-100之前,那么就可以圍繞這兩個條件自定義兩個不同的驗證規則,它們定義如下:

用戶名驗證規則

public class NameValidationRule : ValidationRule
{public override ValidationResult Validate(object value, CultureInfo cultureInfo){if (value != null && value.ToString().Length > 1 && value.ToString().Length <= 10){return new ValidationResult(true, "通過");}return new ValidationResult(false, "用戶名長度1-10個字符");}
}

年齡驗證規則

public class AgeValidationRule : ValidationRule
{public override ValidationResult Validate(object value, CultureInfo cultureInfo){double myValue = 0;if (double.TryParse(value.ToString(), out myValue)){if (myValue >= 1 && myValue <= 100){return new ValidationResult(true, null);}}return new ValidationResult(false, "請輸入 1 至 100的年齡");}
}

在XAML前端代碼中,TextBox輸入框分別綁定了用戶名和年齡,它們在綁定時如何調用驗證規則呢?

<StackPanel Orientation="Horizontal">
? ? <TextBlock Text="姓名:" Margin="5"/>
? ? <TextBox Width="145" Height="25">
? ? ? ? <TextBox.Text>
? ? ? ? ? ? <Binding Path="Person.Name" UpdateSourceTrigger="PropertyChanged">
? ? ? ? ? ? ? ? <Binding.ValidationRules>
? ? ? ? ? ? ? ? ? ? <local:NameValidationRule ValidatesOnTargetUpdated="True" />
? ? ? ? ? ? ? ? </Binding.ValidationRules>
? ? ? ? ? ? </Binding>
? ? ? ? </TextBox.Text>
? ? ? ? <Validation.ErrorTemplate>
? ? ? ? ? ? <ControlTemplate>
? ? ? ? ? ? ? ? <DockPanel>
? ? ? ? ? ? ? ? ? ? <Grid DockPanel.Dock="Right" Width="auto" Height="auto" VerticalAlignment="Center" Margin="3 0 0 0">
? ? ? ? ? ? ? ? ? ? ? ? <TextBlock Width="auto" Height="auto" Foreground="Red"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Text="{Binding ElementName=AdornedElementPlaceholder, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/>
? ? ? ? ? ? ? ? ? ? </Grid>
? ? ? ? ? ? ? ? ? ? <Border BorderBrush="Red" BorderThickness="0" CornerRadius="2">
? ? ? ? ? ? ? ? ? ? ? ? <AdornedElementPlaceholder x:Name="AdornedElementPlaceholder"/>
? ? ? ? ? ? ? ? ? ? </Border>
? ? ? ? ? ? ? ? </DockPanel>
? ? ? ? ? ? </ControlTemplate>
? ? ? ? </Validation.ErrorTemplate>
? ? </TextBox>
</StackPanel>

ValidationRule會把驗證結果保存在AdornedElementPlaceholder的AdornedElement屬性中,所以,需要利用綁定的方法去綁定下面這個路徑。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79344.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79344.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79344.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JavaEE-多線程實戰02

接上 多線程編程實戰01 第三個多線程程序 package thread.test;//定義了一個叫MyThread3的類&#xff0c;實現了Runable接口,所以它必須重寫run()方法 class MyThread3 implements Runnable {Overridepublic void run() {//線程執行的具體內容//進入一個無限循環&#xff0c;…

【無報錯,親測有效】如何在Windows和Linux系統中查看MySQL版本

如何在Windows和Linux系統中查看MySQL版本 MySQL作為最流行的開源關系型數據庫管理系統之一&#xff0c;了解如何查看其版本信息對于開發者和數據庫管理員來說是常用的一個基本操作。本文將詳細介紹在Windows和Linux系統中查看MySQL版本的方法。 文章目錄 如何在Windows和Linu…

數字智慧方案5961丨智慧能源與運維云平臺解決方案(52頁PPT)(文末有下載方式)

詳細資料請看本解讀文章的最后內容。 資料解讀&#xff1a;智慧能源與運維云平臺解決方案 在當今數字化時代&#xff0c;能源管理與設備運維的智能化、高效化成為企業發展的關鍵。智慧能源與運維云平臺解決方案應運而生&#xff0c;為企業提供了全面且先進的能源管理和運維手段…

Qt指南針

Qt寫的指南針demo. 運行結果 滑動調整指針角度 實現代碼 h文件 #ifndef COMPASS_H #define COMPASS_H#include <QWidget> #include <QColor>class Compass : public QWidget {Q_OBJECT// 可自定義屬性Q_PROPERTY(QColor backgroundColor READ backgroundColor WRI…

北大新媒體運營黃金提示詞 | 北大Deepseek系列第七彈《DeepSeek與新媒體運營》,13所大學系列一站下載

今天大師兄給大家推薦的是北京大學Deepseek系列第七彈《DeepSeek與新媒體運營》。 本文檔系統介紹了DeepSeek模型在新媒體運營中的應用&#xff0c;技術原理、實踐案例及行業挑戰。 適用人群&#xff1a;新媒體運營人員、AI研究者、企業決策者。 思維導圖 napkin生成 《老…

2025年真實面試問題匯總(一)

Spingboot中如何實現有些類是否加載 在 Spring Boot 中可以通過 條件化配置&#xff08;Conditional Configuration&#xff09; 來控制某些類是否加載。Spring Boot 提供了一系列 Conditional 注解&#xff0c;允許根據特定條件動態決定 Bean 或配置類是否生效。以下是常見的…

綜合案例建模(2)

文章目錄 螺旋片端蓋多孔扭轉環作業一作業二作業三 螺旋片端蓋 上視基準面畫草圖&#xff0c;拉伸250&#xff0c;向外拔模15度 以地面圓&#xff08;如果不行就轉換實體引用&#xff09;&#xff0c;創建螺旋線&#xff0c;錐形螺紋線15度向外 前視基準面去畫草圖 以上一步草圖…

Qt5與現代OpenGL學習(三)紋理

把第一張圖放到D盤的1文件夾里面&#xff1a;1.png triangle.h #ifndef WIDGET_H #define WIDGET_H#include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QOpenGLVertexArrayObject> #include <QOpenGLShaderProgram> #include <QOpen…

這是一款好用的PDF工具!

用戶習慣有時確實非常頑固&#xff0c;想要改變它可能需要漫長的時間。 比如PDF軟件&#xff0c;我認為國產的福/昕、萬/興等軟件都非常不錯&#xff0c;它們貼合國人的使用習慣&#xff0c;操作起來非常順手。但因為我習慣使用DC&#xff0c;所以在處理PDF文檔時&#xff0c;…

輕松實現CI/CD: 用Go編寫的命令行工具簡化Jenkins構建

在工作中&#xff0c;隨著開發維護的服務越來越多&#xff0c;在很長的一段時間里&#xff0c;我來回在多個服務之間開發、構建、查看容器是否啟動成功。尤其是開發測試階段&#xff0c;需要打開jenkins頁面、搜索應用、再構建、再打開rancher頁面、搜索應用&#xff0c;這一連…

第十六屆藍橋杯 2025 C/C++B組第一輪省賽 全部題解(未完結)

目錄 前言&#xff1a; 試題A&#xff1a;移動距離 試題C&#xff1a;可分解的正整數 試題D&#xff1a;產值調整 試題E&#xff1a;畫展布置 前言&#xff1a; 我參加的是第一輪省賽&#xff0c;說實話第一次參加還是比較緊張的&#xff0c;真到考場上看啥都想打暴力&…

Qt Creator環境編譯的Release軟件放在其他電腦上使用方法

本文解決的問題&#xff1a;將Qt Creator環境編譯的exe可執行程序放到其他電腦上不可用情況 1、尋找windeployqt工具所在路徑" D:\Qt5.12.10\5.12.10\msvc2015_64\bin" &#xff0c;將此路徑配置到環境變量&#xff1b; 2、用Qt Creator環境編譯出Release版本可執行…

使用skywalking進行go的接口監控和報警

安裝 helm upgrade --install skywalking ./skywalking-v1 --namespace skywalking --create-namespace 查看安裝結果 kubectl get pod -n skywalking NAME READY STATUS RESTARTS AGE elasticsearch-6c4ccbf99f-ng6sk 1/1 …

2025年- H16-Lc124-169.多數元素(技巧)---java版

1.題目描述 2.思路 3.代碼實現 import java.util.Arrays;public class H169 {public int majorityElement(int[] nums) {Arrays.sort(nums);int nnums.length;return nums[n/2];}public static void main(String[] args){H169 test07new H169();int[] nums{2,2,1,1,1,2,2};int…

k8s術語pod

Pod概覽 理解Pod Pod是kubernetes中你可以創建和部署的最小也是最簡的單位,pod代表著集群中運行的進程。 Pod中封裝著應用的容器(有的情況下是好幾個容器),存儲、獨立的網絡IP,管理容器如何運行的策略選項。Pod代表著部署的一個單位:kubemetes中應用的一個實例,可能由一個…

《數字圖像處理(面向新工科的電工電子信息基礎課程系列教材)》章節思維導圖

今天看到了幾本書的思維導圖&#xff0c;感觸頗深&#xff0c;如果思維導圖只是章節安排&#xff0c;這樣的思維導圖有毛用。 給出《數字圖像處理&#xff08;面向新工科的電工電子信息基礎課程系列教材&#xff09;》實質內容章節的思維導圖。思維導圖的優勢是邏輯關系和知識…

Nacos簡介—4.Nacos架構和原理二

大綱 1.Nacos的定位和優勢 2.Nacos的整體架構 3.Nacos的配置模型 4.Nacos內核設計之一致性協議 5.Nacos內核設計之自研Distro協議 6.Nacos內核設計之通信通道 7.Nacos內核設計之尋址機制 8.服務注冊發現模塊的注冊中心的設計原理 9.服務注冊發現模塊的注冊中心的服務數…

【MySQL】復合查詢與內外連接

目錄 一、復合查詢 1、基本查詢回顧&#xff1a; 2、多表查詢&#xff1a; 3、自連接&#xff1a; 4、子查詢&#xff1a; 單列子查詢 多行子查詢&#xff1a; 多列子查詢&#xff1a; 在from語句中使用子查詢&#xff1a; 5、合并查詢&#xff1a; union&#xff1…

后端工程師需要掌握哪些基礎技能

后端工程師是構建系統核心邏輯的關鍵角色&#xff0c;需要掌握從基礎到進階的完整技術棧。以下是結合國內實際開發需求的技能樹整理&#xff0c;附帶學習建議&#xff1a; 一、編程語言&#xff08;至少精通1-2種&#xff09; # 國內主流選擇&#xff08;按優先級排序&#x…

萬字重談C++——繼承篇

繼承的概念及定義 繼承的概念 繼承&#xff08;Inheritance&#xff09;機制作為面向對象程序設計中最核心的代碼復用方式&#xff0c;它不僅允許開發人員在保留基礎類特性的前提下進行功能擴展&#xff08;從而創建新的派生類&#xff09;&#xff0c;更重要的是體現了面向對…