還是以上篇導(dǎo)航為基礎(chǔ),完善導(dǎo)航的頁面并為導(dǎo)航的頁面綁定數(shù)據(jù)和顯示數(shù)據(jù)。
這篇學(xué)習(xí)筆記主要記錄兩個(gè)點(diǎn),分別為如下:
- 基于Silverlight 的Windows Phone 數(shù)據(jù)綁定
- 為應(yīng)用程序添加程序欄,額外記錄顯示和隱藏系統(tǒng)托盤(System.Tray)的代碼
1.數(shù)據(jù)綁定
數(shù)據(jù)綁定為基于Silverlight 的應(yīng)用程序提供了一個(gè)簡單的方式來實(shí)現(xiàn)顯示和數(shù)據(jù)之間交互。數(shù)據(jù)顯示從數(shù)據(jù)管理中分離出來。用戶界面與數(shù)據(jù)模型之間的連接或者綁定,允許數(shù)據(jù)在兩者之間流動(dòng)。不一個(gè)綁定被建立,數(shù)據(jù)發(fā)生改變,被綁定到數(shù)據(jù)的UI(用戶界面 )元素能自動(dòng)發(fā)生改變。這本篇 學(xué)習(xí)筆記將針對(duì)Silverlight 提供的控件DataList 為原型講述如何綁定數(shù)據(jù)和刪除數(shù)據(jù)。下面的圖顯示了綁定的概念:
上圖可以分為綁定目標(biāo)和綁定源。
- 綁定目標(biāo)代表綁定的對(duì)象是UI控件,所以必須控件是FrameworkElement的任何一個(gè)DependencyProperty(提供快速的方法計(jì)算值,可與其他動(dòng)態(tài)數(shù)據(jù)交互)。
- 綁定來源包含了來源和目標(biāo)之間的數(shù)據(jù)流的數(shù)據(jù)。來源可以是任何運(yùn)行于CLR的對(duì)象,包括目標(biāo)元素本身或者其他UI元素。
- 數(shù)據(jù)流的方向。Binding 對(duì)象的Mode屬性設(shè)置了數(shù)據(jù)流的方向。分為三種方向:OneTime---目標(biāo)控件屬性只是更新一次,以后的更新會(huì)被忽略。oneWay--數(shù)據(jù)對(duì)象的值會(huì)同步到目標(biāo)控件的屬性,但是目標(biāo)控件的屬性的改變不會(huì)同步到數(shù)據(jù)對(duì)象中。TwoWay--目標(biāo)控件的屬性和數(shù)據(jù)對(duì)象的值相互同步。
- 可選的值轉(zhuǎn)換器,它被應(yīng)用于經(jīng)過值轉(zhuǎn)換器傳遞的數(shù)據(jù)。值轉(zhuǎn)器是一個(gè)類,它實(shí)現(xiàn)了IValueConverter。
原理大致如上,下面看一下要實(shí)現(xiàn)的效果圖:
如圖,點(diǎn)擊圖中畫紅圈的連接,將會(huì)導(dǎo)航到一個(gè)放置DataList的數(shù)據(jù)列表,DataList放置了一列帶圖片和文字的數(shù)據(jù),選中某項(xiàng)則讓刪除按鈕可用,可以指定刪除某項(xiàng)數(shù)據(jù),并實(shí)時(shí)更新到列表中,界面效果如下:
綁定數(shù)據(jù)原理:
為了保證引用的集合發(fā)生改變時(shí)數(shù)據(jù)綁定機(jī)制也能使集合接收通知,Silverlight 使用了事件機(jī)制。數(shù)據(jù)綁定引擎期望當(dāng)一個(gè)集合的值改變時(shí),所發(fā)生的事件是CollectionChanged ,該事件被定義為如下:
這個(gè)集合的實(shí)現(xiàn)應(yīng)該是集合的每一個(gè)改變(添加/編輯/移除集合的成員,程序順序,等)都會(huì)被觸發(fā)到事件。引用事件響應(yīng)變化。這個(gè)事件被定義到INotifyCollectionChanged 接口中。 為使數(shù)據(jù)綁定能自動(dòng)更新到集合,應(yīng)該創(chuàng)建自己的集合并實(shí)現(xiàn)這個(gè)接口。在Silverlight 類庫中提供了兩個(gè)集合,這兩個(gè)集合實(shí)現(xiàn)了這個(gè)接口,我們可以很放心的拿來使用,分別為:ObservableCollection<T>和ReadOnlyObservableCollection<T> 。
- ObservableCollection -代表了一個(gè)動(dòng)態(tài)數(shù)據(jù)集。它會(huì)為集合中的項(xiàng)發(fā)生添加,移除或者整個(gè)列表被刷新等情況實(shí)時(shí)提供通知。
- ReadOnlyObservableCollection -代表了一個(gè)可讀的ObservableCollection。
Tip:兩個(gè)類的數(shù)據(jù)綁定機(jī)制會(huì)對(duì)更新己經(jīng)綁定到集合的對(duì)象時(shí)觸發(fā)的事件做出響應(yīng)。
實(shí)現(xiàn)這個(gè)集合之前,我們有必要先完成一個(gè)Phots 的屬性集,代碼如下:
{
private string _Filename;
public string Filename
{
get { return _Filename;}
set
{
_Filename = value;
NotifyPropertyChanged( " FileName " );
}
}
private BitmapImage_Image;
public BitmapImageImage
{
get { return _Image;}
set
{
_Image = value;
NotifyPropertyChanged( " Image " );
}
}
private void NotifyPropertyChanged( string propertyName)
{
if ( null != PropertyChanged)
PropertyChanged( this , new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandlerPropertyChanged;
}
TIP: INotifyPropertyChanged ,是一個(gè)接口實(shí)現(xiàn)它是為了在數(shù)據(jù)改變的時(shí)候能夠廣播出去,通過屬性名稱通知哪個(gè)屬性名稱發(fā)生了變化。
另外我們還需要一個(gè)工具來,用來通過資源的URI將文件轉(zhuǎn)為可讓圖片接收的BitmapImage類型,代碼如下:
{
public static BitmapImageGetImage( string filename)
{
string imgLocation = Application.Current.Resources[ " ImagesLocation " ].ToString();
StreamResourceInfoimageResource = Application.GetResourceStream( new Uri(imgLocation + filename,UriKind.Relative));
BitmapImageimage = new BitmapImage();
image.SetSource(imageResource.Stream);
return image;
}
完成了上述兩個(gè)類,打開圖片對(duì)應(yīng)的Xaml,我這里的名稱路徑在:/Views/PicturesView/Default.xaml。在該頁面的ContentPanel中加入一個(gè)DataList 控件,并為其數(shù)據(jù)模板添加內(nèi)容顯示窗器,比如本例以橫向顯示的StackPanel中放置了一個(gè)圖片控件和一個(gè)文本控件用來顯示圖片和圖片名稱,XML代碼如下:
< StackPanel Orientation ="Vertical" >
< StackPanel Orientation ="Horizontal" >
< Button x:Name ="btnRemoveSelection" Content ="RemoveImage" Click ="btnRemoveSelection_Click" IsEnabled ="False" />
</ StackPanel >
< ListBox x:Name ="lstPictures" Width ="450" Height ="520" Margin ="10" SelectionChanged ="lstPictures_SelectionChanged" >
< ListBox.ItemTemplate >
< DataTemplate >
< StackPanel Orientation ="Horizontal" >
< Image Source =" {BindingImage} " Width ="100" Stretch ="Uniform" HorizontalAlignment ="Center" />
< TextBlock Text =" {BindingFilename} " TextWrapping ="Wrap" />
</ StackPanel >
</ DataTemplate >
</ ListBox.ItemTemplate >
</ ListBox >
</ StackPanel >
</ Grid >
做Asp.net 的朋友趕快過來圍觀,這個(gè)DataList 數(shù)據(jù)綁定的方法不是就是ASP.NET常用的寫法嗎?只是來源做了處理使用Silverlight 的寫法,不過看樣子和格式都與Asp.Net 的DataList 數(shù)據(jù)綁定很相似。好了,之后進(jìn)入CS文件,引用這一命名空間:
聲明上述提到的ObservableCollection對(duì)象,將Photo對(duì)象放進(jìn)去,我在做Android 的時(shí)候喜歡寫數(shù)據(jù)源的時(shí)候這樣寫:List<HashMap<String,Object>> list=new ArrayList<HashMap<String,Object>>(); 然后去自定義一個(gè)數(shù)據(jù)源,感覺靈活性比較強(qiáng),WP7還沒試過,就先暫時(shí)使用這種數(shù)據(jù)對(duì)象來實(shí)現(xiàn)數(shù)據(jù)的更新顯示吧。
定義好后,為集合中的PHOTO對(duì)象存值和設(shè)置DataList的事件并與刪除按鈕交互,所有代碼如下:
/// 此事件定義了當(dāng)數(shù)據(jù)改變時(shí)通知集合觸發(fā)事件
/// </summary>
// publiceventNotifyCollectionChangedEventHandlerCollectionChanged;
ObservableCollection < Photo > photos = new ObservableCollection < Photo > ();
private void initializePhotos()
{
photos.Add( new Photo(){
Filename = " Butterfly.jpg " ,
Image = Utils.GetImage( " Butterfly.jpg " )
});
photos.Add( new Photo()
{
Filename = " Chrysanthemum.jpg " ,
Image = Utils.GetImage( " Chrysanthemum.jpg " )
});
photos.Add( new Photo()
{
Filename = " Desert.jpg " ,
Image = Utils.GetImage( " Desert.jpg " )
});
photos.Add( new Photo()
{
Filename = " Field.jpg " ,
Image = Utils.GetImage( " Field.jpg " )
});
photos.Add( new Photo()
{
Filename = " Tulips.jpg " ,
Image = Utils.GetImage( " Tulips.jpg " )
});
photos.Add( new Photo()
{
Filename = " Flower.jpg " ,
Image = Utils.GetImage( " Flower.jpg " )
});
photos.Add( new Photo()
{
Filename = " Hydrangeas.jpg " ,
Image = Utils.GetImage( " Hydrangeas.jpg " )
});
photos.Add( new Photo()
{
Filename = " Butterfly.jpg " ,
Image = Utils.GetImage( " Butterfly.jpg " )
});
photos.Add( new Photo()
{
Filename = " Jellyfish.jpg " ,
Image = Utils.GetImage( " Jellyfish.jpg " )
});
photos.Add( new Photo()
{
Filename = " Koala.jpg " ,
Image = Utils.GetImage( " Koala.jpg " )
});
photos.Add( new Photo()
{
Filename = " Leaves.jpg " ,
Image = Utils.GetImage( " Leaves.jpg " )
});
photos.Add( new Photo()
{
Filename = " Lighthouse.jpg " ,
Image = Utils.GetImage( " Lighthouse.jpg " )
});
photos.Add( new Photo()
{
Filename = " Penguins.jpg " ,
Image = Utils.GetImage( " Penguins.jpg " )
});
photos.Add( new Photo()
{
Filename = " Rocks.jpg " ,
Image = Utils.GetImage( " Rocks.jpg " )
});
photos.Add( new Photo()
{
Filename = " Tulip.jpg " ,
Image = Utils.GetImage( " Tulip.jpg " )
});
photos.Add( new Photo()
{
Filename = " Window.jpg " ,
Image = Utils.GetImage( " Window.jpg " )
});
}
public Default()
{
InitializeComponent();
initializePhotos();
lstPictures.ItemsSource = photos;
}
private void btnRemoveSelection_Click( object sender,RoutedEventArgse)
{
if ( null != lstPictures.SelectedItem)
{
photos.Remove(lstPictures.SelectedItem as Photo);
}
}
private void lstPictures_SelectionChanged( object sender,SelectionChangedEventArgse)
{
if ( null != lstPictures.SelectedItem)
{
btnRemoveSelection.IsEnabled = true ;
}
if (photos.Count == 0 )
{
btnRemoveSelection.IsEnabled = false ;
}
}
2.應(yīng)用程序欄
在很多情況下我們會(huì)需要提供跨應(yīng)用程序的通用功能。一些情況下,我們可能想要為頁面提供一些符合某些條件時(shí)才出現(xiàn)的特殊功能。另外一些情況下,您只希望獲得更多的屏幕空間,這些情況下,Windows Phone 提供了應(yīng)用程序欄。
要為應(yīng)用程序添加應(yīng)用程序欄,需要在App.xaml 注冊(cè)。本篇學(xué)習(xí)的內(nèi)容注冊(cè)一個(gè)菜單和兩個(gè) 按鈕,一個(gè)菜單導(dǎo)航到About 頁面,另外一個(gè)按鈕跳轉(zhuǎn)到Image列表。打開App.xaml,在Application.Resouces節(jié)點(diǎn)內(nèi),輸如下代碼并為其添加事件響應(yīng):
< shell:ApplicationBar x:Key ="MainAppBar" IsVisible ="True" >
<!-- 菜單項(xiàng)Abou -->
< shell:ApplicationBar.MenuItems >
< shell:ApplicationBarMenuItem Text ="About" Click ="ApplicationBarMenuItem_Click" />
</ shell:ApplicationBar.MenuItems >
<!-- 應(yīng)用程序條按鈕 -->
< shell:ApplicationBar.Buttons >
< shell:ApplicationBarIconButton Text ="Web" IconUri ="ie_icon.png" Click ="ApplicationBarIconButton_Click" />
< shell:ApplicationBarIconButton Text ="Images" IconUri ="pictures_Icon.png" Click ="ImageEvent_Click" />
</ shell:ApplicationBar.Buttons >
</ shell:ApplicationBar >
進(jìn)入APP.xaml.cs在自動(dòng)生成的事件句柄內(nèi),鍵入如下代碼實(shí)現(xiàn)跳轉(zhuǎn):
{
PhoneApplicationFrameroot = Application.Current.RootVisual as PhoneApplicationFrame;
root.Navigate( new Uri( " /About " ,UriKind.Relative));
}
private void ApplicationBarIconButton_Click( object sender,EventArgse)
{
}
private void ImageEvent_Click( object sender,EventArgse)
{
PhoneApplicationFrameroot = Application.Current.RootVisual as PhoneApplicationFrame;
root.Navigate( new Uri( " /Pictures " ,UriKind.Relative));
}
在你需要顯示應(yīng)用程序欄的頁面的phone:PhoneApplicationPage節(jié)點(diǎn)指定ApplicationBar來源,比如本文的指定方式:
x:Class ="DataBind.MainPage"
xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone ="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell ="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d ="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc ="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable ="d" d:DesignWidth ="480" d:DesignHeight ="768"
FontFamily =" {StaticResourcePhoneFontFamilyNormal} "
FontSize =" {StaticResourcePhoneFontSizeNormal} "
Foreground =" {StaticResourcePhoneForegroundBrush} "
SupportedOrientations ="Portrait" Orientation ="Portrait"
shell:SystemTray.IsVisible ="True"
ApplicationBar =" {StaticResourceMainAppBar} "
>
看看截圖效果吧:
源碼比較大,有需要的EMAIL我: terryyhl@gmail.com
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
