Caliburn.Micro開發框架介紹
Caliburn是一套基於XAML的開發框架,它小巧而強大。利用它不但能提升開發效率,還能夠提升XAML程序開發的可維護行、可擴展性和可測試性。Caliburn.Micro則是專門針對Windows phone開發的版本。html
MVVM簡介
MVVM源於微軟的軟件開發模式,能夠粗略的認爲它是MVC模式的發展,原來Controller的職能被拆分,其中值轉換器(Value Converter)和綁定器(binder)已經由框架實現,程序員能夠更關注在邏輯實現上。MVVM的開發基於事件驅動,實現UI層和邏輯層的分離,從而使UI設計人員和程序員各施其職。MVVM中的View Model在Model和View之間扮演着值轉換器的角色,把Model的數據交給View去綁定,把View的數據提交給Model;同時也要實現mediator設計模式,成爲View和Model之間的邏輯協調者。程序員
Caliburn.Micro簡介
Caliburn.Micro使用各類的配置和約定使得代碼工做變得簡潔。好比:你無需使用ViewModelLocator爲某個View定位它的View Model,在Caliburn.Micro中只須要按照約定把View的名字加上後綴ViewModel,就是它的View Model的名字,如:MainPage和MainPageViewModel。shell
Caliburn.Micro自動把ViewModel綁定到View的DataContext。若是ViewModel的屬性名和控件的名稱相同,那麼就會自動綁定上。若是該屬性的值發生變化,控件的也能獲得更新。編程
此外,Caliburn.Micro還爲Windows phone的特性提供輔助,例如:tombstone的管理,應用程序生命週期和launcher。bootstrap
固然,你也能夠自定義各類約定。設計模式
準備工做
下載
Caliburn.Micro能夠經過Visualstudio的NuGet工具得到,也能夠在其官網下載發佈包、源代碼和例子。http://caliburnmicro.codeplex.com/app
入口bootstrapper
Bootstrapper是Caliburn.Micro的入口,全部的ViewModel必須在這個類裏註冊,不然Caliburn.Micro沒法爲你的View和ViewModel創建關聯。框架
若是須要自定義命名約定,也是在這個類裏定義。異步
咱們新建一個WP8工程,先刪除默認建立的MainPage.xaml,建立Views目錄,在Views目錄下建立MainPage.xaml,建立ViewModels目錄,在ViewModels下建立MainPageViewModel.cs類,修改WMAppManifest.xml中的起始頁面爲Views/MainPage.xaml。async
在工程的根目錄下建立bootstrapper.cs,其內容以下。
-
public
class
AppBootstrapper :
PhoneBootstrapper
-
-
PhoneContainer container;
-
-
protected override void Configure()
-
-
container =
new PhoneContainer(RootFrame);
-
-
container.RegisterPhoneServices();
-
-
container.PerRequest<MainPageViewModel>();
-
-
-
-
-
static void AddCustomConventions()
-
-
-
-
-
protected override object GetInstance(Type service, string key)
-
-
return container.GetInstance(service, key);
-
-
-
protected override IEnumerable<object> GetAllInstances(Type service)
-
-
return container.GetAllInstances(service);
-
-
-
protected override void BuildUp(object instance)
-
-
container.BuildUp(instance);
-
-
初始化bootstrapper
修改App.xml,初始化bootstrapper。
-
-
x:Class=
"CSH.IntelliHIS.WP8.App"
-
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:local=
"clr-namespace:CSH.IntelliHIS.WP8">
-
-
-
-
<local:AppBootstrapper x:Key="bootstrapper" />
-
-
-
修改App.xml.cs,默認的初始化代碼已經不須要了。
-
public
partial
class
App :
Application
-
-
-
-
-
-
命名約定(naming convention)
命名約定讓Caliburn.Micro能自動關聯起View和View Model,若是咱們運行工程,瀏覽MainPage頁面,則MainPageViewModel自動被實例化。
接下來就能夠看看Caliburn.Micro是如何扮演值轉換器的角色,看它是如何在View和ViewModel之間傳遞和轉換值,以便View綁定這些值。
咱們在ViewModel裏增長一個叫Name的屬性(Property)。
-
public
class
MainPageViewModel:
PropertyChangedBase
-
-
public MainPageViewModel()
-
-
-
-
-
-
-
-
-
-
-
NotifyOfPropertyChange(() => Name);
-
-
-
在View裏增長一個文本控件,使用和這個屬性相同的名字,值就會自動綁定上去。(Caliburn.Micro也支持原有的binding語法)
<TextBlock x:Name="Name"/>
注意,ViewModel繼承了PropertyChangedBase類,在Name屬性被修改的時候,調用NotifyOfPropertyChange方法發出通知,這使得Name屬性被修改時,View裏的綁定控件TextBlock能自動地更新。
行爲(Actions)
命令(Commands)
Caliburn.Micro使用一種叫作行爲的機制,使得ViewModel響應View的事件。它很簡單。
View控件定義了名字。
<Button Content="Show name"x:Name="ShowNameAction" />
ViewModel的方法只要使用相同名字就會獲得調用。
public void ShowNameAction()
{
MessageBox.Show("Clicked");
}
固然,也支持自定義調用方法。需先引用
xmlns:i=」clrnamespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity」xmlns:cal=」clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro」
View裏這樣定義
-
<Button x:Name=
"ShowName">
-
-
<i:EventTrigger EventName=
"Click">
-
<cal:ActionMessage MethodName=
"ShowNameAction" />
-
-
</i:Interaction.Triggers>
-
Caliburn.Micro也有簡寫方式,但Blend不支持。使用Message.Attach,在Event和Action關鍵字後使用你想要的事件名和方法名。
<Button cal:Message.Attach="[Event Click] = [Action ShowName]" />
控制行爲
Caliburn.Micro有一個約定,若是一個控件綁定在一個屬性上,則另外一個屬性能很容易控制它的命令可否被執行,只須要這個新屬性的名字是那個綁定屬性的名字加上Can關鍵字。例如:一個Button的名字和ViewModel的屬性名字叫Execute,則ViewModel裏叫CanExecute的屬性能控制該Button可否被點擊。
還有更復雜一點的狀況,一個控件控制另外一個控件可否被執行。例如:CheckBox控制Button可否被激活。
-
-
<Button x:Name=
"ShowName" Content=
"Click me" />
-
<CheckBox x:Name=
"IsEnabled" Content=
"IsEnabled" />
-
CheckBox綁定到isEnabled,Button綁定到ShowName,CheckBox值改變的同時通知Button的控制屬性CanShowName,從而實現關聯控制。
-
public
class
MainPageViewModel:
PropertyChangedBase
-
-
-
-
-
get {
return isEnabled; }
-
-
-
-
NotifyOfPropertyChange(() => IsEnabled);
-
NotifyOfPropertyChange(() => CanShowName);
-
-
-
-
-
get {
return IsEnabled; }
-
-
-
-
MessageBox.Show(
"Clicked");
-
-
集合(Collections)
View的列表控件和ViewModel的集合屬性若是同名也能實現綁定,Selected關鍵字前綴加上屬性名的單數形式就能實現選中控制。
例如:ListBox控件使用複數形式的Items名稱
-
<ListBox x:Name=
"Items">
-
-
-
-
<TextBlock Text=
"{Binding}" />
-
-
-
-
ViewModel的屬性同名Items實現綁定。
-
private ObservableCollection<
string> items;
-
public ObservableCollection<
string> Items
-
-
-
-
-
-
NotifyOfPropertyChange(() => Items);
-
-
SelectedItem實現選中控制。(注意:Selected+單數形式Item)
-
private
string selectedItem;
-
public
string SelectedItem
-
-
get {
return selectedItem; }
-
-
-
-
NotifyOfPropertyChange(() => SelectedItem);
-
-
-
依賴注入(Dependency Injection)
Caliburn.Micro有依賴注入的功能。用戶類要在依賴注入時被使用到,就要在Bootstrapper的Configure函數向依賴注入容器註冊,Caliburn.Micro既提供每次建立新實例的模式,也提供單一實例模式。同時Caliburn.Micro會自動註冊一些系統工具類。
-
protected override void Configure()
-
-
container =
new PhoneContainer(RootFrame);
-
container.RegisterPhoneServices();
-
-
container.PerRequest<MainPageViewModel>();
-
container.PerRequest<Page2ViewModel>();
-
-
container.Singleton<IVisitDataProvider, VisitDataProvider>();
-
-
在ViewModel被實例化時,若是其構造函數帶有某種類型接口爲參數,則依賴注入容器會提供它們的實例。例子以下。
導航(Navigation)
Windows Phone使用NavigationService來完成頁面間跳轉,ViewModel若是要跳轉頁面,應利用依賴注入獲得它的實例。
-
public
class
MainPageViewModel :
PropertyChangedBase
-
-
private
readonly INavigationService navigationService;
-
public MainPageViewModel(INavigationService navigationService)
-
-
this.navigationService = navigationService;
-
-
-
-
navigationService.UriFor<Page2ViewModel>()
-
-
-
注入導航參數
若是導航時帶有參數,Caliburn.Micro會自動把參數值注入到同名屬性。
例如:跳轉時帶上Name參數
-
-
-
navigationService.UriFor<Page2ViewModel>()
-
.WithParam(x => x.Name,
"Matteo")
-
-
其導航字符串爲/Page2View.xaml?Name=Matteo,則Page2的同名屬性Name在實例化時就會被注入值。若是有控件綁定了該屬性,則導航到該頁面時就能顯示出值。
-
public
class
Page2ViewModel:
PropertyChangedBase
-
-
-
-
-
-
-
-
-
NotifyOfPropertyChange(() => Name);
-
-
-
墓碑(Tombstoning)
應用程序被切換至後臺時,若是有值須要暫存,Caliburn.Micro提供了很簡潔的解決方法,這比普通XAML程序處理生命週期裏各個事件要容易的多。咱們只須要建立一個StorageHandler<T>的繼承類,T是你要保存臨時值的ViewModel。
例如,在程序切換至後臺時,須要暫存View里名爲Name的文本框的值,即暫存MainPageViewModel的Name屬性。
-
public
class
MainPageModelStorage:
StorageHandler<
MainPageViewModel>
-
-
public override void Configure()
-
-
-
-
-
InPhoneState()函數把值暫存在內存中,程序退出後就不存在。相對應的InAppSettings()則會持久保存。
深度連接(Deep Links)
Windows phone支持跳過首頁的實例化,經過URL連接直接打開應用程序裏的某個頁面,並可攜帶參數。Caliburn.Micro的依賴注入和屬性注入機制能保證深度連接的正常打開。
例如:
<StackPanel>
<TextBoxText="{Binding Name}" />
<ButtonContent="Create secondary tile" x:Name="CreateTile" />
</StackPanel>
該ViewModel的按鈕事件動態建立一個Tile,點擊該Tile打開深度連接,這裏的連接使用了首頁。
-
public
class
MainPageViewModel:
PropertyChangedBase
-
-
-
-
-
-
-
-
-
NotifyOfPropertyChange(() => Name);
-
-
-
-
-
ShellTileData tile =
new StandardTileData
-
-
-
-
ShellTile.Create(
new Uri(
"/Views/MainPage.xaml?Name=Matteo",
-
UriKind.Relative), tile);
-
-
生命週期的事件
ViewModel並不是WP8頁面的繼承類,爲了能在ViewModel裏響應頁面基類PhoneApplicationPage生命週期的事件,Caliburn.Micro介紹了Screen類。當一個應用初次打開,依次會觸發下列事件。
-
public
class
MainPageViewModel:
Screen
-
-
protected override void OnViewAttached(object view, object context)
-
-
base.OnViewAttached(view, context);
-
Debug.WriteLine(
"OnViewAttached:ViewModel和View創建關聯時被調用");
-
-
protected override void OnInitialize()
-
-
-
Debug.WriteLine(
"OnInitialize:初始化結束");
-
-
protected override void OnViewReady(object view)
-
-
-
Debug.WriteLine(
"OnViewReady:初始化結束,準備繪製");
-
-
protected override void OnViewLoaded(object view)
-
-
-
Debug.WriteLine(
"OnViewLoaded:頁面和子控件所有初始化完成");
-
-
protected override void OnActivate()
-
-
-
Debug.WriteLine(
"OnActivate:切換成爲當前窗口");
-
-
protected override void OnDeactivate(bool close)
-
-
base.OnDeactivate(close);
-
Debug.WriteLine(
"OnDeactivate:切換至後臺");
-
-
Screen的OnActivate和OnDeactivate事件是最常使用的事件,它們分別對應了頁面OnNavigatedTo和OnNavigatedFrom事件。值得注意的是,ViewModel加載數據應儘可能避免在構造函數和初始化函數中實行,而應該在OnActivate中。
消息傳遞(Messaging)
Caliburn.Micro爲應用程序內已經打開的多個ViewModel之間提供消息傳遞的功能。
例子:從頁面1打開頁面2,點擊頁面2的SendMessage Button向頁面1發送一個消息,回退到頁面1就會看到這個值顯示在文本框裏。
以下定義的消息類
-
public
class
SampleMessage
-
-
public
string Name {
get;
set; }
-
public SampleMessage(string name)
-
-
-
-
消息接收者須要實現接口IHandle<T>,本例T就是SampleMessage,並須要接受消息接口IEventAggregator的注入。
注意:消息接收者須要調用IEventAggregator的Subscribe函數訂閱消息。
-
public
class
MainPageViewModel:
Screen,
IHandle<
SampleMessage>
-
-
private
readonly IEventAggregator eventAggregator;
-
private
readonly INavigationService navigationService;
-
-
-
-
-
-
-
-
-
NotifyOfPropertyChange(() => Name);
-
-
-
-
public MainPageViewModel(IEventAggregator eventAggregator, INavigationService
-
-
-
this.eventAggregator = eventAggregator;
-
this.navigationService = navigationService;
-
eventAggregator.Subscribe(
this);
-
-
-
-
-
navigationService.UriFor<SecondPageViewModel>().Navigate();
-
-
-
public void Handle(SampleMessage message)
-
-
-
-
消息發送者只須要接受IEventAggregator的注入,並用它的Publish方法發送消息。
-
public
class
SecondPageViewModel:
Screen
-
-
private
readonly IEventAggregator eventAggregator;
-
public SecondPageViewModel(IEventAggregator eventAggregator)
-
-
this.eventAggregator = eventAggregator;
-
-
public void SendMessage()
-
-
eventAggregator.Publish(
new SampleMessage(
"Matteo"));
-
-
View和ViewModel之間的通信
View類只要獲得IEventAggregator的實例也能在Views和ViewModels之間接收或發送消息。
此時咱們須要改造Bootstrapper類,要獲得其container變量,就能夠調用其GetAllInstances或GetInstance獲得IEventAggregator。
例如:
-
public
class
Bootstrapper :
PhoneBootstrapper
-
-
-
public PhoneContainer container {
get;
set; }
-
-
-
MainPage的View類經過bootstrapper中Container的GetAllInstances方法獲得IEventAggregator實例,並能夠訂閱或發送消息。
-
public
partial
class
MainPage :
PhoneApplicationPage,
IHandle<
SampleMessage>
-
-
private IEventAggregator eventAggregator;
-
-
-
-
-
Bootstrapper bootstrapper = Application.Current.Resources[
"bootstrapper"]
-
-
IEventAggregator eventAggregator =
-
bootstrapper.container.GetAllInstances(
typeof
-
(IEventAggregator)).FirstOrDefault()
as IEventAggregator;
-
this.eventAggregator = eventAggregator;
-
eventAggregator.Subscribe(
this);
-
-
public void Handle(SampleMessage message)
-
-
MessageBox.Show(message.Name);
-
-
Launcher與Chooser
Caliburn.Micro借用IEventAggregator消息類還提供了調用Launcher和Chooser的功能。
例子:調用Launcher打開地圖程序。
-
public
class
MainPageViewModel:
Screen
-
-
public MainPageViewModel(IEventAggregator eventAggregator)
-
-
this.eventAggregator = eventAggregator;
-
eventAggregator.Subscribe(
this);
-
-
-
-
eventAggregator.RequestTask<MapsTask>(task =>
-
-
task.SearchTerm =
"Milan";
-
-
-
Chooser因爲須要接收返回值,須要實現IHandle<TaskCompleted<T>>接口。
-
public
class
MainPageViewModel:
Screen,
IHandle<
TaskCompleted<
PhoneNumberResult>>
-
-
private
readonly IEventAggregator eventAggregator;
-
public MainPageViewModel(IEventAggregator eventAggregator)
-
-
this.eventAggregator = eventAggregator;
-
-
protected override void OnActivate()
-
-
eventAggregator.Subscribe(
this);
-
-
-
protected override void OnDeactivate(bool close)
-
-
eventAggregator.Unsubscribe(
this);
-
base.OnDeactivate(close);
-
-
public void OpenContact()
-
-
eventAggregator.RequestTask<PhoneNumberChooserTask>();
-
-
public void Handle(TaskCompleted<PhoneNumberResult> message)
-
-
MessageBox.Show(message.Result.DisplayName);
-
-
注意:因爲移動應用生命週期的特殊性,ViewModel應該在OnActivate和OnDeactivate事件裏訂閱消息和取消訂閱。
用戶服務
用戶自定義的服務類,能夠經過依賴注入提供給使用方,前提是必須在Bootstrapper的Configure函數中註冊。這樣的服務類通常使用接口編程。
例子, 先定義數據和服務類接口。
-
public
interface
IFeedService
-
-
Task<List<FeedItem>> GetNews(
string url);
-
-
-
-
public
string Title {
get;
set; }
-
public
string Description {
get;
set; }
-
public Uri Url {
get;
set; }
-
實現類
-
public
class
FeedService:
IFeedService
-
-
public
async Task<List<FeedItem>> GetNews(
string url)
-
-
WebClient client =
new WebClient();
-
string content =
await client.DownloadStringTaskAsync(url);
-
XDocument doc = XDocument.Parse(content);
-
-
doc.Descendants(
"rss").Descendants(
"channel").Elements(
"item").Select(x =>
new
-
-
-
-
Title = x.Element(
"title").Value,
-
Description = x.Element(
"description").Value
-
-
-
-
在bootstrapper的Configure註冊該類
-
protected override void Configure()
-
-
container =
new PhoneContainer(RootFrame);
-
container.RegisterPhoneServices();
-
container.PerRequest<MainPageViewModel>();
-
container.PerRequest<IFeedService, FeedService>();
-
-
而後使用類的構造函數就能使用依賴注入獲得它的實例。
-
public
class
MainPageViewModel:
Screen
-
-
private
readonly IFeedService feedService;
-
private List<FeedItem> news;
-
public List<FeedItem> News
-
-
-
-
-
-
NotifyOfPropertyChange(() => News);
-
-
-
public MainPageViewModel(IFeedService feedService)
-
-
this.feedService = feedService;
-
-
public async void LoadWebsite()
-
-
-
feedService.GetNews(
"http://feeds.feedburner.com/qmatteoq_eng");
-
-
用戶類的單一實例
Caliburn.Micro也支持把用戶服務類註冊爲單一實例,每一個使用者獲得的都是同一個實例。利用這個特性,多個ViewModel能夠共享數據。
-
protected override void Configure()
-
-
container =
new PhoneContainer(RootFrame);
-
container.RegisterPhoneServices();
-
container.PerRequest<MainPageViewModel>();
-
container.PerRequest<DetailPageViewModel>();
-
container.PerRequest<IFeedService, FeedService>();
-
container.Singleton<DataService>();
-
-
應用程序工具條(Application Bar)
因爲系統默認Applicationbar不是頁面控件,不支持綁定。Caliburn.Micro提供了代替類Caliburn.Micro.BindableAppBar(能夠經過NuGet得到)。
View中引用。
xmlns:bab=」clrnamespace:Caliburn.Micro.BindableAppBar;assembly=Caliburn.Micro.BindableAppBar」
並在頁面中添加該控件。
-
<Grid x:Name=
"LayoutRoot" Background=
"Transparent">
-
-
<RowDefinition Height=
"Auto"/>
-
<RowDefinition Height=
"*"/>
-
-
-
<bab:BindableAppBar x:Name=
"AppBar">
-
<bab:BindableAppBarButton x:Name=
"AddItem"
-
Text=
"{Binding AddItemText}"
-
IconUri=
"{Binding Icon}"
-
Visibility=
"{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"
-
-
<bab:BindableAppBarMenuItem x:Name=
"RemoveItem"
-
-
-
-
自定義命名約定
爲了讓按鈕在Click事件發生時不可用,咱們在bootstrapper中增長自定義命名約定。
-
static void AddCustomConventions()
-
-
ConventionManager.AddElementConvention<BindableAppBarButton>(
-
Control.IsEnabledProperty,
"DataContext",
"Click");
-
ConventionManager.AddElementConvention<BindableAppBarMenuItem>(
-
Control.IsEnabledProperty,
"DataContext",
"Click");
-
該約定把IsEnabled屬性綁定給Click事件。
下面ViewModel能給自定義bar提供按鈕文本、圖標、可見狀態和響應事件。
-
public
class
MainPageViewModel:
Screen
-
-
private
string addItemText;
-
public
string AddItemText
-
-
get {
return addItemText; }
-
-
-
-
-
NotifyOfPropertyChange(() => AddItemText);
-
-
-
-
-
-
-
-
-
-
NotifyOfPropertyChange(() => Icon);
-
-
-
-
-
-
get {
return isVisible; }
-
-
-
-
NotifyOfPropertyChange(() => IsVisible);
-
-
-
public MainPageViewModel()
-
-
-
Icon =
new Uri(
"/Assets/AppBar/appbar.add.rest.png", UriKind.Relative);
-
-
-
-
-
MessageBox.Show(
"Item added");
-
-
-
-
MessageBox.Show(
"Item removed");
-
-
Pivot和Panorama
Pivot和Panorama做爲Windows phone的特點控件普遍的到使用,因爲Panorama的選中事件有Bug,致使子頁面的生命週期的事件不完整,因此重點介紹Pivot。
Caliburn.Micro爲Pivot提供了工具類,能把各個功能區分離成子頁面,每一個子頁面都有本身的生命週期。
爲了能讓Pivot集成多個頁面做爲子頁面,首先須要在bootstrapper中註冊這些ViewModel。
Conductor類
Conductor類做爲多頁面的管理者,Pivot主頁面的ViewModel須要繼承它。
例如:Pivot主頁面繼承Conductor類,便擁有了Items屬性,利用依賴注入獲得子頁面的實例,並把子頁面添加到Items集成屬性中,以便Conductor管理它們。
-
public
class
PivotViewModel:
Conductor<
IScreen>.
Collection.
OneActive
-
-
private
readonly PivotItem1ViewModel item1;
-
private
readonly PivotItem2ViewModel item2;
-
public PivotViewModel(PivotItem1ViewModel item1, PivotItem2ViewModel item2)
-
-
-
-
-
protected override void OnInitialize()
-
-
-
-
-
-
-
而View類中的Pivot控件僅須要指定其名稱爲Items便可。
-
<Grid x:Name=
"LayoutRoot" Background=
"Transparent">
-
-
<phone:Pivot Title=
"MY APPLICATION"
x:Name="Items" SelectedItem=
"{Binding
-
ActiveItem, Mode=TwoWay}">
-
<phone:Pivot.HeaderTemplate>
-
-
<TextBlock Text=
"{Binding DisplayName}" />
-
-
</phone:Pivot.HeaderTemplate>
-
-
子頁面須要繼承Screen類,其DisplayName屬性做爲Title顯示在Pivot上。
-
public
class
PivotItem1ViewModel:
Screen
-
-
public PivotItem1ViewModel()
-
-
DisplayName =
"First pivot";
-
-
延遲加載(Lazy Loading)
在構造函數或初始化函數中加載數據會帶來很糟糕的用戶體驗。Pivot的子頁面也具備完整的生命週期事件,能夠在ViewModel的OnActivate()事件中加載數據。
例子,Pivot子頁面1負責讀取RSS,咱們先定義數據和數據操做類,
-
-
-
public
string Title {
get;
set; }
-
public
string Description {
get;
set; }
-
-
public
static
class
RssParser
-
-
public static IEnumerable<FeedItem> ParseXml(string content)
-
-
XDocument doc = XDocument.Parse(content);
-
-
doc.Descendants(
"rss").Descendants(
"channel").Elements(
"item").Select(x =>
new
-
-
-
Title = x.Element(
"title").Value,
-
Description = x.Element(
"description").Value
-
-
-
-
再定義View中的綁定行爲。
-
<ListBox x:Name=
"FeedItems">
-
-
-
-
<TextBlock Text=
"{Binding Path=Title}" />
-
-
-
-
ViewModel類的OnActivate()事件裏使用異步方法下載並解析數據,而後更新綁定源。
-
public
class
PivotItem1ViewModel:
Screen
-
-
public PivotItem1ViewModel()
-
-
-
-
protected override async void OnActivate()
-
-
-
WebClient client =
new WebClient();
-
-
client.DownloadStringTaskAsync(
"http://feeds.feedburner.com/qmatteoq_eng");
-
IEnumerable<FeedItem> feedItems = RssParser.ParseXml(result);
-
FeedItems = feedItems.ToList();
-
-
private List<FeedItem> _feedItems;
-
public List<FeedItem> FeedItems
-
-
get {
return _feedItems; }
-
-
-
-
NotifyOfPropertyChange(() => FeedItems);
-
-
-