深入理解MVVM模式中Silverlight的Trigger、Action和Behavior及Silverlight的繼承機制


  接觸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都可以使用,是不是感覺很強大!源碼已經上傳,在下面下載。

 

點擊這里下載源碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM