接觸Silverlight已經有兩三個月了,開始一直感覺他和Winform很相似,拖拖控件就行了,所以一直把經歷放在了研究后台和服務器交互和性能優化上面,很少去仔細研究Silverlight的頁面。前幾天,公司突然讓修改一個Winform的項目,再回過頭來看Winform,有種"不堪回首"的感覺。
十一長假即將來臨,在這里先祝大家假期快樂。今天難得有空,抽出點時間研究了一下Silverlight的繼承和觸發器,拿出來和大家分享一下。Silverlight和WPF中頁面布局使用的都是XAML,頗為相似,學習WPF的也可以參考一下。
一、Silverlight中的繼承
那么先來說一下Silverlight中的繼承吧,我們經常在后台代碼中使用繼承,實現代碼的重用。那么在前端頁面是否可以使用繼承,實現代碼和控件的重用呢?答案是可以的。通過學習繼承,我們可以更深入的理解XAML。下面來寫一個Demo,一起來看一下,首先新建一個Silverlight項目,名字就叫SLDemo吧,添加默認的網站,建完項目后目錄如下:
既然要說繼承,那么首先要有個父類,新加一個Class,名字就叫BaseView,添加一些屬性,代碼如下:
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SLDemo { public class BaseView : UserControl { public string Title { get; set; } public int WinWidth { get; set; } public int WinHeight { get; set; } } }
這里簡單添加一些屬性,我們看到所有的頁面控件都繼承自UserControl,所以我們這個父類也要繼承UserControl,然后修改MainPage代碼,來繼承我們這個類。
這里要注意的是,Silverlight里面頁面和后台cs文件要繼承自同一個父類,所以前端和后台都要改,后台cs文件很簡單,修改后代碼如下:
namespace SLDemo { public partial class MainPage : BaseView { public MainPage() { InitializeComponent(); } } }
只是把父類UserControl改成BaseView即可,然后來看前端頁面的修改方法:
<sld:BaseView x:Class="SLDemo.MainPage" xmlns:sld="clr-namespace:SLDemo" 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" mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="600"> <Grid x:Name="LayoutRoot" Background="White"> </Grid> </sld:BaseView>
來看一下代碼變成什么樣了?是不是和之前大不一樣了,<Usercontrol></Usercontrol>沒有了?是不是有種"高大尚"的感覺,瞬間感覺讓人看不懂了?下面我來解釋一下:
注意看第二行,我們引入了一個命名空間,XAML中引入命名空間就是
xmlns:{前綴}="clr-namespace:{命名空間}"
這里我們把前綴寫成了sld(SLDemo的前三個字母),然后把Usercontrol改成我們的BaseView,和后台cs文件統一。實際上,XAML中應該這樣寫:
<命名空間:類名></命名空間:類名>
但是由於Usercontrol是系統默認的,所以前面的命名空間就省了。接下來,先拖幾個控件上去看看,會發生什么,這里拖一個TabControl和一個Button吧,代碼如下:
<sld:BaseView x:Class="SLDemo.MainPage" xmlns:sld="clr-namespace:SLDemo" 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" mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="600" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <Grid x:Name="LayoutRoot" Background="White"> <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="308,119,0,0" Name="button1" VerticalAlignment="Top" Width="75" /> <sdk:TabControl Height="100" HorizontalAlignment="Left" Margin="210,205,0,0" Name="tabControl1" VerticalAlignment="Top" Width="200" /> </Grid> </sld:BaseView>
可以看到,Button和之前一樣,tabcontrol和之前還是一樣(都要引用命名空間),這里主要說一下命名空間,可以看到上面多了一行代碼:
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
這里引入TabControl的命名空間,看我標紅的,然后用這個前綴去添加Tabcontrol,所以以后我們引用自己的自定義控件也是這樣,先引用命名控件,然后通過前綴來訪問。
當然,寫了這么多,我們還是再寫一個控件,其實Silverlight中Page大多用來顯示控件,頁面都是由控件堆出來的,然后在窗體顯示時,設置他的Content屬性來呈現。
到這里,大家就可以通過繼承來重寫和擴展控件了。(今天先說到這里,以后會詳細介紹開發自定義控件)。
二、Silverlight的Trigger、Action和Behavior
現在比較流行用MVVM來開發Silverlight項目,目的是實現XAML和代碼的分離。今天就來說一下Trigger、Action和Behavior.
首先來說一下三者的關系:
Trigger : 觸發器,就像他的名字一樣,是用來監聽事件,然后執行某段代碼
Action: 動作,就是執行一段代碼
Behavior: 行為,看起來好像不太好理解,其實他可以看作是Trigger和Action的組合
首先來說一下Trigger和Action吧,首先來寫一個Action,新建一個類MyAction,在寫代碼之前,我們要先引入一個命名空間,如圖:
然后在代碼中引用命名空間System.Windows.Interactivity;繼承TriggerAction類,代碼如下:
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Interactivity; namespace SLDemo { public class MyAction : TriggerAction<DependencyObject> { protected override void Invoke(object parameter) { MessageBox.Show("你觸發了一個Action!"); } } }
這里我們重寫了Invoke方法,讓他彈出一條消息。下面我們來使用這個Action,讓他來響應一個事件,修改XAML代碼如下:
<sld:BaseView x:Class="SLDemo.MainPage" xmlns:sld="clr-namespace:SLDemo" 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:i="http://schemas.microsoft.com/expression/2010/interactivity" mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="600" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <Grid x:Name="LayoutRoot" Background="White"> <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="308,119,0,0" Name="button1" VerticalAlignment="Top" Width="75"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <sld:MyAction /> </i:EventTrigger> </i:Interaction.Triggers> </Button> </Grid> </sld:BaseView>
這里我們給一個按鈕添加了一個Trigger來偵聽單擊事件,然后綁定MyAction,運行后我們單擊按鈕,會彈出消息框。
下面,我們來給Action傳遞一個參數,當然你可以多加幾個,我們就傳遞一個BtnName屬性吧,修改MyAction代碼如下:
namespace SLDemo { public class MyAction : TriggerAction<DependencyObject> { public string BtnName { get; set; } protected override void Invoke(object parameter) { MessageBox.Show("你觸發了一個Action!按鈕名稱是:" + this.BtnName); } } }
我們只是添加了一個屬性,下面來看看如何使用:
運行效果如下:
我們就像平常寫XAML那樣,寫一個屬性就可以傳遞一個參數到Action里面,當然這里也可以綁定一個變量。但是實際開發中,我們不需要這樣做,因為我們把變量寫在ViewModel中,寫Action可以給一些Combox綁定SelectedChanged事件,目的還是實現布局和代碼分離。
Behavior
下面來看一下神奇的Behavior吧,有了Behavior,可以實現一些特效的重復使用,下面來寫一個簡單的例子看一下,就寫一個關於Textbox的吧,新建一個類,名字叫做TextboxBehavior,代碼如下:
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Interactivity; namespace SLDemo { public class TextboxBehavior : Behavior<TextBox> { protected override void OnAttached() { base.OnAttached(); AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged); } void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e) { if (AssociatedObject.Text.Length < 6) { AssociatedObject.Foreground = new SolidColorBrush(Color.FromArgb(200, 255, 0, 0)); } else { AssociatedObject.Foreground = new SolidColorBrush(Color.FromArgb(200, 0, 255, 0)); } } } }
然后在XAML中添加如下代碼:
這個時候,Textbox就綁定了我們的TextboxBehavior了,運行看下效果:
當輸入的內容小於六個字符的時候,顯示紅色
大於等於六個字符時就變成綠色。
我們一旦寫好了這個Behavior,所有頁面的Textbook都可以使用,是不是感覺很強大!源碼已經上傳,在下面下載。