在WinRT XAML Toolkit中發現另一個CodePlex中的架構AsyncUI。感覺很有意思,使用它可以用C# 5.0的async/await特性來等待介面上的事件。
比如這樣,介面上有一個Button的Name是btn,然後在Page的Loaded事件中可以這樣寫。
//+ using WinRTXamlToolkit.AsyncUI;
//Main_Loaded_1為Page的Loaded事件
//主介面上有一個Name為btn的Button
private async void Main_Loaded_1(object sender, RoutedEventArgs e)
{
//通過ButtonExtensions.WaitForClickAsync方法來返回一個Task<RoutedEventArgs>
var args = await btn.WaitForClickAsync();
//Click執行後非同步等待代碼
Show("按鈕被點擊:" + args.OriginalSource);
}
//顯示MessageDialog
static async void Show(string s)
{
await new MessageDialog(s).ShowAsync();
}
代碼使用AsyncUI中ButtonExtensions.WaitForClickAsync方法,通過await非同步等待返回的Task<RoutedEventArgs>對象,這樣實現非同步等待Button的Click事件。當Button被點擊後,相應事件會執行!如:
原理則是利用AsyncUI中的EventAsync.FromRoutedEvent方法,這個方法會返回另一個類型RoutedEventHandlerTaskSource的Task屬性。這個類型會使用EventAsync.FromRoutedEvent的參數來對目標事件進行顯示註冊和取消註冊操作。如下ButtonExtensions.WaitForClickAsync的方法原始碼:
public static async Task<RoutedEventArgs> WaitForClickAsync(this ButtonBase button)
{
return await EventAsync.FromRoutedEvent(
eh => button.Click += eh,
eh => button.Click -= eh);
}
最後RoutedEventHandlerTaskSource使用.NET中的TaskCompletionSource將對應UI事件的結果設定給TaskCompletionSource,並返回RoutedEventArgs作為Task的返回結果。當Task運行完畢後,EventAsync.FromRoutedEvent方法中的取消註冊事件的代碼會被運行。