Essential Silverlight翻譯連載(5、6章)

mrhaozi發表於2010-01-06

5 互動和事件處理

Silverlight互動

宣告式語言表示XAML提供了很多可能,包括建立所有型別的形狀(見第4章),動畫元素(見第6章),播放聲音影片資料(見第7章)。但如果您在Silverlight中加入少量JavaScript程式碼,將會釋放出它的真實的力量。JavaScript本身是一個強大的語言,但開發者也可以在Silverlight中使用JavaScript API。本書第三部分,特別是第8章,將更詳細地講述JavaScript訪問。雖然本書主要關注的是宣告式語言XAML,但沒有指令碼,很多事將不能做。

這一章解釋Silverlight事件處理。特別是什麼是事件,怎麼獲取和處理它們。大部份的事件處理程式碼都以“XAML code-behind”的方式存在於Filename.xaml.js檔案中。從技術手段上來說,javaScript程式碼可以放置在任何JavaScript檔案中,只需要在主HTML檔案中透過<script>標籤來引用就行了。如果在.xaml.js檔案中使用觸發XAMLJavaScript程式碼,而在html.js檔案中加入觸發JavaScript程式碼的HTML頁面,就可以使應用程式更易於打包和開發。

大部份的檔案清單最少有三個檔案---HTML檔案,XAML檔案,一個或多個JavaScript檔案。部分檔案的內容總是很相似,例如createSilverlight()方法的程式碼。從下一個例子開始,我們將調整內含的XAML檔案的,將不再給出createSilverlight()方法的程式碼。就好象之前沒有給出HTML檔案的程式碼一樣。儘管如此,您也可以在本書配套的程式碼()中找到例子的完整程式碼。

提示:如果對HTML,XAML和JavaScript檔案的作用有任何疑問,請複習第2章的基本概念。

事件和事件處理

Silverlight事件是當Silverlight應用程式執行時會發生某些事情。這些事情可能是滑鼠單擊,滑鼠移動,鍵盤輸入,應用程式接受或失去焦點,應用程式開始完全載入或是其他類似的事情。所有事件依賴於一個物件,這樣不管滑鼠指標在矩形之上還是文字之上,單擊時都會有所不同。

Silverlight現在支援超過24個事件,將來的版本可能會更多。本章只關心最重要的一些事件,並提供之前不曾提及到的事件的相關背景知識。

事件處理是一個程式碼塊,在事件發生(或叫觸發)時被執行。這裡所說的事件和事件處理和HTML中的JavaScript事件概念非常接近。

宣告事件處理

有兩種途徑給一個事件分配一個事件處理---使用宣告式方法或使用程式碼。讓我們從第一個選項開始,並使用滑鼠事件。Silverlight支援幾種滑鼠事件,其中之一是使用者單擊滑鼠左鍵時發生的MouseLeftButtonDown(在滑鼠被釋放前發生)。

讓我們回顧一下第二章的第一個例子“Hello World”,它包含了三個元素,外層的<Canvas>,一個<Rectangle>和一個<TextBlock>。我們給這三個元素新增事件處理。新增一個事件處理非常容易:新增一個和事件名稱相同的屬性(在此例中,使用LeftMouseButtonDown而不是JavaScript中的OnLeftMouseButtonDown)。這個屬性的值是JavaScript的方法名稱。當事件觸發時將呼叫這個方法一次。例5-1顯示了這個包括三個事件處理的XAML檔案:

5-1 使用事件處理,XAML檔案(MouseClick.xaml

<Canvas xmlns=""

xmlns:x=""

MouseLeftButtonDown="mouseClick">

<Rectangle Width="200" Height="75" Stroke="Orange" StrokeThickness="15"

MouseLeftButtonDown="mouseClick" />

<TextBlock FontFamily="Arial" FontSize="32" Canvas.Left="30" Canvas.Top="20"

Foreground="Black" Text="Silverlight"

MouseLeftButtonDown="mouseClick" />

Canvas>

JavaScript事件處理方法存在於MouseClick.js.xaml檔案內,它象ASP.NET事件處理方法一樣接收兩個引數:

sender

接收到事件的那個物件的引用,並會呼叫事件處理。

eventArgs

事件的資訊,例如,當處理一個滑鼠事件時,可以得到當前滑鼠的位置。簡單的事件處理方法所做的是顯示哪個元素觸發了事件。為了實現這個功能,需要使用到sender引數的字串表達。例如,當<TextBlock>元素觸發了事件,sender.toString()所返回的是TextBlock。例5-2中的.xaml.js檔案中的“XAML code-behind”程式碼演示了這項功能。

5-2 使用事件處理,XAML JavaScript檔案(MouseClick.xaml.js

function mouseClick(sender, eventArgs)

{

alert('Ouch, says ' + sender.toString() + 'l');

}

現在,當您單擊文字塊時,將會彈出兩個JavaScript視窗:一個是文字塊的,另一個是canvas的(圖5-1)。這叫做“事件浮升機制”。無論何時,當一個元素接收到一個事件,它會把事件向上傳播到父節點(在本例中,<TextBlock>把事件傳播給<Canvas>)。如果父節點本身還有父節點,事件還會繼續向上傳播。這種機制和JavaScriptExplorer瀏覽器裡的事件機制很相似,它經常用於巢狀的XAML結構,並且需要為幾個物件新增事件處理。當然例5-1的這種機制是很少使用的,一般只給一個元素新增事件處理。

譯者注:由於使用了XAML的程式碼隱藏檔案,所以這個例子需要的是四個檔案,除了前面一章所講的三個檔案外,還多了一個xaml.js檔案。例5-2所演示的就是這個檔案。這樣就需要在html檔案內多加一行程式碼引用這個檔案。在html檔案中的

程式碼後面新增一行

這樣就可以正常執行程式了。後面的例子也是這樣處理。

Essential Silverlight翻譯連載(5、6章)

當您想改變觸發事件的物件時,把Sender屬性賦給事件處理方法非常方便。 一般的規則是把每個屬性(例如物件的Foreground)暴露給JavaScript。實際上,當JavaScript試圖訪問屬性時,Silverlight會從中擷取這些請求並進行轉換,使得Silverlight屬性可以正確地被獲取。這些請求不是大小寫敏感的,您可以使用Foregroundforeground。本書使用駝峰命名法:Foreground變為foregroundFontSize變為fontSize。下面再介紹兩個滑鼠事件:MouseHover(當滑鼠指標移動至元素的顯示區域之上)和MouseLeave(當滑鼠指標離開元素顯示區域時)。例5-3建立了一個XAML檔案,它使用了這兩種事件,並指定了前景色。

5-3 改變事件目錄屬性,XAML檔案(MouseHover.xaml

<Canvas xmlns=""

xmlns:x="">

<Rectangle Width="200" Height="75" Stroke="Orange" StrokeThickness="15" />

<TextBlock FontFamily="Arial" FontSize="32" Text="Silverlight"

Canvas.Left="30" Canvas.Top="20"

Foreground="LightGray" MouseEnter="high" MouseLeave="low" />

Canvas>

XAML的程式碼隱藏的JavaScript檔案(例5-4)訪問sender引數並設定foreguound屬性。結果顯示為文字首先顯示為亮灰色,但當滑鼠移動到它上面時,它會變為黑色。當滑鼠離開文字顯示區域時,它又變回為亮灰色。圖5-2顯示了文字的兩種狀態。

5-4 改變事件目標屬性,XAML JavaScript檔案(MouseHover.xaml.js

function high(sender, eventArgs) {

sender.Foreground = 'Black';

}

function low(sender, eventArgs) {

sender.Foreground = 'LightGray';

}

Essential Silverlight翻譯連載(5、6章)

事件偵聽

第二種是使用程式碼的方法:使用事件偵聽把一個事件處理賦給一個事件。您可以安排一段程式碼“偵聽”是否有事件發生。如果發生了,將會進行適當地處理。宣告事件處理的主要優勢是很容易移除一個事件偵聽。不利條件是事件偵聽並非自動生成的,特別對於一些有很強的HTML背景的開發人員。但當您第一次使用它,並在程式中使用它根本不困難。

讓我們開始一段XAML程式碼。正如您所見,並沒有專門針對單擊事件的事件處理屬性。好,這有另外一個重要的事件:Loaded。一個元素只會觸發一次Loaded事件,如例5-5,整個XAML檔案被完全載入後,我們使用這個事件建立實際的事件偵聽。

5-5 使用事件偵聽,XAML檔案(MouseClickListener.xaml

<Canvas xmlns=""

xmlns:x=""

Loaded="canvasLoaded">

<Rectangle Width="200" Height="75" Stroke="Orange" StrokeThickness="15" />

<TextBlock FontFamily="Arial" FontSize="32" Canvas.Left="30" Canvas.Top="20"

Foreground="Black" Text="Silverlight"

x:Name="ClickTarget"/>

Canvas>

建立事件偵聽

時間證明一切,我們來看看下面這段建立事件偵聽的JavaScript程式碼:

window.onload = function() {

// 這裡建立事件偵聽

}

HTML頁面標記過完全載入時,頁面的Load事件將會被觸發一次。當然這並不代表所有相關檔案包括JavaScript類庫和XAML檔案已經被完全載入。當在您的本地計算機上測試它時,它可能不會被執行,因為檔案是從速度很快的硬碟上載入的。然而Internet可能會有嚴重的延遲,所以您不能依賴於這種方法。這也是為什麼使用根元素的Loaded事件來初始化Silverlight應用程式並不常用的原因之一。

但現在對於事件偵聽來說,首先你不得不尋找跟事件偵聽關聯的元素。在例5-5中我們應該注意到,元素有一個名稱屬性(準確地說是xName,)。SilverlightJavaScript API可以透過名稱找到相應的元素,實現這個功能您只需要使用findName()方法,它支援XAML檔案中的每個元素。

我們可以訪問XAML中的元素。需要記住,事件處理方法自動接收一個sender的引用做為他們的第一個引數。所以我們可以使用sender和它的findName()方法來訪問文字塊:

function canvasLoaded(sender, eventArgs) {

var textblock = sender.findName('ClickTarget');

}

一旦獲得了文字塊(或其他元素),就可以把事件處理賦給它。完成這個任務的方法是addEventListener(),它有兩個引數:

1. 事件的名稱

2. 事件處理,也可以是一個方法的引用,或一個匿名方法

textblock.addEventListener('MouseLeftButtonDown',mouseClick);

以上所執行的是實際的事件處理,它輸出兩個元素,觸發的事件和它的名稱。例5-6顯示了JavaScript檔案的完整程式碼,圖5-3是瀏覽器中的輸出效果。

5-6 使用事件偵聽,XAML JavaScript檔案(MouseClickListener.xaml.js

function canvasLoaded(sender, eventArgs) {

var textblock = sender.findName('ClickTarget');

textblock.addEventListener(

'MouseLeftButtonDown',

mouseClick);

}

function mouseClick(sender, eventArgs) {

alert('Ouch, says ' + sender.toString() + '“'+ sender.name + '”!');

}

Essential Silverlight翻譯連載(5、6章)

5-3 使用程式給事件偵聽賦值

移除事件偵聽將會使它被“Mouse Position”的程式碼段所覆蓋。

滑鼠事件

Silverlight 1.0支援5個滑鼠事件,其中三個前面已經介紹過:

MouseEnter

滑鼠指標移動到物件顯示區域內

MouseLeave

滑鼠指標從物件顯示區域離開

MouseMove

滑鼠移動

MouseLeftButtonDown

滑鼠左鍵按下

MouseLeftButtonUp

滑鼠左鍵單擊並釋放

這些事件是自解釋的,但應該解釋一下MouseLeftButtonDownMouseLeftButtonUp之間的不同之處。單使用者在某元素上單擊滑鼠,首先會觸發MouseLeftButtonDown事件,然後是MouseLeftButtonUp事件。所以滑鼠單擊是在MouseLeftButtonUp事件被觸發之後才完成。實際上它們之間只有在一種情況下才會有區別:使用者把滑鼠指標移動到元素之上,按下滑鼠按鈕不放,再次移動滑鼠離開元素。當您使用MouseLeftButtonUp事件,它將不會被觸發,這符合一些場影的需要(如按鈕事件),但不符合別一些場影的需要(如滑鼠拖動)。

提示:滑鼠事件針對向量圖格式SVG的機制如支援三種滑鼠事件:按鈕按下,按鈕釋放,按鈕單擊。

滑鼠位置

當您捕獲一個滑鼠事件,可能想知道滑鼠指標當前的位置。關於“在哪裡”的問題前面已經回答過,就是物件之上,更具體的問題是“在哪個位置?”。這一點可以轉而關注事件處理方法的第二個引數eventArgs。它提供了這些資訊,並支援getPosition()方法。

getPosition()方法支援任意的XML元素做為引數。如果設定了它,getPosition()方法將得到滑鼠相對於給定元素的座標。否則,將得到一個絕對座標(例如,您沒有提供引數或引數是一個null值)。

getPosition()方法的返回值是一個帶有兩個屬性xy的物件,它代表了滑鼠指標水平和垂直位置。在Web中,原點表示的是左上角的位置。

5-7所包含的XAML標記跟蹤了滑鼠的移動。注意<TextBlock>屬性是如何用於顯示滑鼠指標位置的。另外還需注意主canvasLoaded事件所執行的方法是canvasLoaded()

5-7 顯示滑鼠位置,XAML檔案(MousePosition.xaml

<Canvas xmlns=""

xmlns:x=""

Loaded="canvasLoaded">

<Rectangle Width="200" Height="75" Stroke="Orange" StrokeThickness="15" />

<TextBlock FontFamily="Arial" FontSize="28" Canvas.Left="25" Canvas.Top="25"

Foreground="Black"

Text="X: ?? Y: ??" x:Name="MousePosition" />

Canvas>

JavaScript程式碼的任務是當滑鼠移動時確定並輸出當前滑鼠指標的位置。相關的事件名稱是MouseMove,想象中事件偵聽的程式碼應該如下:

function canvasLoaded(sender, eventArgs) {

sender.addEventListener(

'MouseMove',

//事件偵聽的引用或程式碼);

}

現在所需做的事只是寫事件偵聽,這裡我們將使用匿名方法。它使用getPosition()方法確定滑鼠位置並寫入文字框中。例5-8是完整的JavaScript程式碼,圖5-4可以看到它在瀏覽器中的效果。

5-8 顯示滑鼠位置,XAML JavaScript檔案(MousePosition.xaml.js

function canvasLoaded(sender, eventArgs) {

sender.addEventListener('MouseMove',

function(sender, eventArgs) {

var x = eventArgs.getPosition(null).x;

var y = eventArgs.getPosition(null).y;

sender.findName('MousePosition').text=

'X: '+ x + ' Y: ' + y;

}

);

}

Essential Silverlight翻譯連載(5、6章)

5-4 顯示當前滑鼠位置

前面曾經提到過,您可以移除事件偵聽。為此您可以在繫結了事件偵聽的物件上呼叫removeEventListener()方法。第一個引數還是事件,但第二個引數可能會讓您感到吃驚,它是事件偵聽的引用(因為您可以在一個事件上繫結多個事件偵聽)。您可以透過在呼叫addEventListener()方法時儲存其返回值來得到這個引用。

為了示範這種機制,我們再次使用滑鼠移動,但這一次在單擊文字時顯示。我們開始於前面的例5-7中的XAML標記,但檔名改為MousePositionToggle.xamlJavaScript程式碼也做了很多改變。首先定義兩個全域性變數。一個用於存放被繫結的事件處理,另一個是一個布林值,用於用於通知指令碼當前是否跟蹤滑鼠位置。

var

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16396910/viewspace-1030334/,如需轉載,請註明出處,否則將追究法律責任。

相關文章