0

Silverlight ビューに TabControl があり、その ItemsSource を ViewModel の TabItems ObservableCollection にバインドしてタブをロードしています。

新しいタブを開くには、それを作成してロードするのに少し時間がかかります。その間、BusyIndi​​cator を実行したいと思います。

それらはViewModelで作成およびロードされるため、非同期ではないため、「ロード」メソッドを呼び出す前にIsBusyプロパティを設定すると表示されません。

バックグラウンドワーカーで設定しようとしましたが、TabItem を作成して TabItems リストに追加するとクラッシュします (UnauthorizedAccessException)。

何か案が???前もって感謝します。

4

2 に答える 2

2

タスクを使用します ( AsyncCtp with Silverlight 4 ):

public void Load(){
    this.IsBusy = true;
    Task.Factory.StartNew(()=> DoHeavyWork())
        .ContinueWith( t => this.IsBusy = false);
}

Async CTP またはVS2012/Silverlight 5で新しい async/await 機能を使用できると、さらに良くなります。

public async void Load(){
    try{
        this.IsBusy = true;

        await Task.Factory.StartNew(()=> DoHeavyWork());
    }
    finally
    {       
        this.IsBusy = false;
    }
}

編集

バックグラウンド タスクで ObservableCollection を更新していると仮定します。コレクションの更新を処理するハンドラーは UI スレッドで実行されないため、実際には問題が発生します。そのため、バインディング システムのようにコレクションの更新はスレッド セーフではありません。これを機能させるには、UI スレッドで ObservableCollection にアイテムを追加する必要があります。一度にすべてのアイテムを取得できる場合は、次のようにすることができます。

public async void Load(){
    try{
        this.IsBusy = true;

        // Returns the fetched items
        var items = await Task.Factory.StartNew(()=> DoHeavyWork());

        // This will happen in the UI thread because "await" returns the
        // control to the original SynchronizationContext
        foreach(var item in items)
            this.observableCollection.Add(item);
    }
    finally
    {       
        this.IsBusy = false;
    }
}

バッチでロードする必要がある場合は、この回答で提案したように、現在の Dispatcher を使用してアイテムをコレクションに追加できます。

于 2012-11-23T11:54:15.083 に答える
0

これは、UI の要素、または UI に反映されるデータを変更するコレクションにアクセスしようとすると発生します。これは実際にはクロス スレッドの例外です。バックグラウンド ワーカーを作成すると、基本的に別のスレッドが作成されます。したがって、バックグラウンド ワーカーからメイン UI スレッドの変数にアクセスすることはできません。

于 2012-11-25T13:19:14.360 に答える