Visual Studio 11を落として少し遊んでみました。前々から新機能としてUIスレッド以外からItemsControlにバインドされたObservableCollection
まずは、既存のVisual Stduio 2010で.NET Framework 4でお試しです。MVVM Light Toolkitを使ってさくっと以下のようなViewModelを作ります。コマンドが実行されるとUIスレッド以外からコレクションに要素が追加されるという単純なものです。
namespace CollectonChangedSample.ViewModel { using System.Collections.ObjectModel; using System.Threading.Tasks; using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; public class MainViewModel : ViewModelBase { public MainViewModel() { } #region Peopleプロパティ private ObservableCollection<Person> _people = new ObservableCollection<Person>(); public ObservableCollection<Person> People { get { return _people; } } #endregion private RelayCommand _addPersonAsyncCommand; /// <summary> /// Gets the AddPersonAsyncCommand. /// </summary> public RelayCommand AddPersonAsyncCommand { get { return _addPersonAsyncCommand ?? (_addPersonAsyncCommand = new RelayCommand( () => { // UIスレッド以外からコレクションにアイテムを追加 Task.Factory.StartNew(() => { this.People.Add(new Person { Name = "sample" }); }); })); } } } public class Person { public string Name { get; set; } } }
XAMLでは単純にCommandとコレクションをバインドするためのコントロールを置いてます。
<Window x:Class="CollectonChangedSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" DataContext="{Binding Source={StaticResource Locator}, Path=Main}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <StackPanel Name="stackPanel1"> <Button Content="Async" Name="button1" Command="{Binding Path=AddPersonAsyncCommand}" /> </StackPanel> <ListBox Grid.Row="1" Name="listBox1" ItemsSource="{Binding Path=People}" DisplayMemberPath="Name" /> </Grid> </Window>
これを実行してボタンを押すと下図の通り例外が出てしまいます。これが今までの動作です。
では、新機能とやらを試してみましょう。Visual Studio 2010で作成したプロジェクトをVisual Studio 11で開きます。そしてプロジェクトのプロパティで.NET Framework 4から4.5に変更します。
そして、リビルドして実行して同じ操作をするとうまくいくはず・・・・!!と思ってたら以下のように同じエラーがorz
むぅ。MSDNのこの英文をTOEIC400点に届かない英語力で見る限り大丈夫そうなのに・・・。
Accessing collections on non-UI Threads WPF enables you to access and modify data collections on threads other than the one that created the collection. This enables you to use a background thread to receive data from an external source, such as a database, and display the data on the UI thread. By using another thread to modify the collection, your user interface remains responsive to user interaction.
読み間違えてるのかな?それとも、まだ実装されてない?