WP7有約(七):實現鈴聲設置的播放圖標的效果
WP7有約(七):實現鈴聲設置的播放圖標的效果
Written by Allen Lee
sjcxyf同學通過站內消息提到這樣一個問題:
我現在想做一個功能就是當ListPicker彈出全屏幕的時候每一項前面是一個播放圖片,后面是音樂名稱,然后我點擊前面的播放的時候播放當前的音樂,不讓他選擇這一項的值并返回 要選擇后面的字之后才返回 就是像Phone 7真機里面設置鈴聲那種效果怎么做?
我們來看一個山寨版的鈴聲設置,如圖1所示,無論用戶單擊鈴聲名字還是它左邊那個播放圖標,都會關閉ListPicker頁面。sjcxyf同學想要的效果是單擊播放圖標將會播放對應的鈴聲,而單擊鈴聲名字才是確認選擇。問題是,即使你單擊鈴聲下面的空白地方,ListPicker頁面也會關閉,為什么?

圖 1 山寨版鈴聲設置
查看ListPickerPage.xaml.cs文件,我們將會發現ListPicker頁面的ListBox控件添加了Tap事件處理程序,如代碼1所示。從中我們不難看出,ListPicker頁面表現出來的行為是預期的,即在單選模式下,單擊ListBox控件里的選項或者空白地方將會關閉ListPicker頁面。于是,sjcxyf同學的需求可以重新描述成在用戶單擊播放圖標時防止ListBox控件的事件處理程序被執行,但是,怎樣才能做到?
代碼 1 ListBox控件的Tap事件處理程序
private void OnPickerTapped(object sender, System.Windows.Input.GestureEventArgs e)
{
// We listen to the tap event because SelectionChanged does not fire if the user picks the already selected item.
// Only close the page in Single Selection mode.
if (SelectionMode == SelectionMode.Single)
{
// Commit the value and close
SelectedItem = Picker.SelectedItem;
ClosePickerPage();
}
}
Silverlight支持一種叫做路由事件(routed event)的概念,這種事件的觸發會從子元素沿著對象樹向上傳遞給各個父元素,直至到達根元素為止。并非所有事件都是路由事件,但Tap事件剛好就是路由事件,換句話說,當用戶單擊播放圖標時,ListBox控件作為播放圖標的父元素,雖然不是直接包含的父元素,也能感知傳遞過來的Tap事件。于是,sjcxyf同學的需求可以重新描述成防止播放圖標的Tap事件向上傳遞給父元素,但是,怎樣才能做到?
Tap事件處理程序的第二個參數有一個Handled屬性,這個屬性正是用來處理這種需求的。假設播放圖標是一個Image控件,如代碼2所示,我們可以為它添加一個Tap事件處理程序,并在里面把Handled屬性設為true,如代碼3所示,這樣,Silverlight的事件系統將會停止把Tap事件向上傳遞給各個父元素。
代碼 2 播放圖標的XAML代碼
<Image Source="/play.png" Stretch="None" HorizontalAlignment="Left"
VerticalAlignment="Center" Tap="Image_Tap" Margin="0,0,12,0"/>
代碼 3 播放圖標的Tap事件處理程序
private void Image_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
// 添加播放音樂的代碼
e.Handled = true;
}
不過,當用戶單擊播放圖標時,當前選中的鈴聲也會發生改變,這顯然不是Windows Phone 7的鈴聲設置的做法。我們希望單擊播放圖標時只是播放鈴聲,但不改變當前選中的鈴聲,如果此時按Back鍵返回,鈴聲設置將會維持原狀。這個效果的實現方式和前面的一樣,只不過這次換成了MouseLeftButtonUp事件,因此我把它留給你課后實踐一下。


浙公網安備 33010602011771號