2011-07-12 15 views
0

私は以下のようにsynfusionタイルビューを持っています。これらの項目のObservableコレクションの読み込み中にUIを実行する方法

http://i.stack.imgur.com/JkrRS.jpg

最大化項目テンプレートがTreeViewコントロールです。 treeview items SourceはObservable Collectionにバインドされています。これらのアイテムの1つを最大化すると、以下のようにViewModelからデータがロードされます。 MaximizedItemChangedイベントにあります。

private void tileViewControl_Exchanges_MaximizedItemChanged(object sender, TileViewEventArgs args) 
{ 
    if (args.Source != null) 
    { 
     TileViewControl tileViewControl = (TileViewControl)sender; 
     TileViewItem tvi = (TileViewItem)args.Source; 

     PanelViewModel panelViewModel = (PanelViewModel)tileViewControl.ItemContainerGenerator.ItemFromContainer(tvi); 

     String currentSelectedPanelID = GetSelectedPanelID(tileViewControl); 

     // below function will load all the treeview items. 
     SetSelectedExchangeID(tileViewControl, exchangePanelViewModel.ExchangeID); 
    } 
} 

しかし、treeviewには何千もの項目があります。だからMaximizeをクリックすると、しばらく時間がかかり、プログラムがハングします。アイテムをスムーズに最大化し、ツリービューアイテムをバックグラウンドでロードする方法はありますか?私がしたいのは、ツリービューがロードされている間に読み込みアニメーションを表示することですが、最大化すると(8秒または9秒間ハングした後)、ツリービューは既にロードされています。

編集:コードの先頭にSetSelectedExchangeIDを追加しました。

public static readonly DependencyProperty SelectedExchangeIDProperty = 
    DependencyProperty.RegisterAttached("SelectedExchangeID", 
    typeof(String), 
    typeof(UC_Contract_List), 
    new UIPropertyMetadata(new PropertyChangedCallback(SelectedExchangeIDPropertyChanged))); 

static void SelectedExchangeIDPropertyChanged(
    DependencyObject depObj, 
    DependencyPropertyChangedEventArgs eventArgs) 
{ 
    TileViewControl tileViewControl = (TileViewControl)depObj; 
    ItemContainerGenerator itemContainerGenerator = tileViewControl.ItemContainerGenerator; 
    String newPanelID = (String)eventArgs.NewValue; 

    if (newPanelID != null) 
    { 
     if (tileViewControl.Visibility == Visibility.Visible) 
     { 
      foreach (PanelViewModel exchangePanel in tileViewControl.Items) 
      { 
       if (exchangePanel.ExchangeID.Equals(newExchangeID)) 
       { 
        TileViewItem tvi = (TileViewItem)itemContainerGenerator.ContainerFromItem(exchangePanel); 
        try 
        { 
         if (tileViewControl.tileViewItems != null) 
         { 
          if (tvi.TileViewItemState != TileViewItemState.Maximized) 
          { 
           tvi.TileViewItemState = TileViewItemState.Maximized; 
          } 
         } 
        } 
        catch (Exception e) { } 
        break; 
       } 
      } 
     } 
    } 
    else 
    { 
     foreach (PanelViewModel exchangePanel in tileViewControl.Items) 
     { 
      TileViewItem tvi = (TileViewItem)itemContainerGenerator.ContainerFromItem(exchangePanel); 
      tvi.TileViewItemState = TileViewItemState.Normal; 
     } 
    } 
} 

public static void SetSelectedExchangeID(DependencyObject depObj, String exchangeID) 
{ 
    depObj.SetValue(SelectedExchangeIDProperty, exchangeID); 
} 

public static String GetSelectedExchangeID(DependencyObject depObj) 
{ 
    return (String)depObj.GetValue(SelectedExchangeIDProperty); 
}  

そしてViewModel中:

String _selectedExchangeID;   
public String SelectedExchangeID 
{ 
    get { return this._selectedExchangeID; } 
    set 
    { 
     if (value == null) 
     { 
      this.ClearPanels(); 
      this._selectedExchangeID = value; 
     } 
     else 
     { 
      this._selectedExchangeID = value; 
      PanelViewModel curPanelViewModel = this.GetPanelViewModel(this._selectedExchangeID); 
      if (curPanelViewModel != null) 
      { 
       curPanelViewModel.Activate(); // this will add to the observable collection for Treeview ItemsSource 
      } 
     } 
     this.OnPropertyChanged("SelectedExchangeID"); 
    } 
} 
+0

'SetSelectedExchangeID'のコードを表示できますか? – ChrisWue

答えて

1

あなたはすべてが利用可能である場合にのみ、バックグラウンドスレッドで非同期に処理/重い負荷のタスクを行うと、UIディスパッチャを使用してフォアグラウンドスレッドと同期することで、オブジェクトことを行うことができますし、処理される。

BackgroundWorkerの詳細については、MSDNを参照してください。

非同期タスクを実行する唯一の方法はBackgroundWorkerではありません。 Tasks(.net 4.0で導入されました)またはBeginInvoke/EndInvokeを選ぶことができます。

重いタスクが完了したら、次のようにフォアグラウンドスレッドと同期することができます。 まず(ビューコンストラクタを言うことができます)UIスレッド上でディスパッチャを初期化します。

Dispatcher _UIDispatcher; 

public MyView 
{ 
    ... 
    _UIDispatcher = Dispatcher.CurrentDispatcher; 
} 

次にロードした後で、同期完了:

public void SyncPostLoading(IEnumerable<Something> myData) 
{ 
    _UIDispatcher.BeginInvoke(DispatcherPriority.ContextIdle, System.Threading.ThreadStart)delegate() 
    { 
      foreach(Something something in myData) 
      myObervableCollection.Add(something); 
     }); 
} 
+0

私は、コレクションの読み込みに問題がないことを知りました。 Maximized ItemTemplateには、ツリービューをホストしている別のusercontrolがあります。 Maximizeをクリックすると、usercontrolがロードされ、最小化するとusercontrolがアンロードされます。だから、私はviewmodelのコレクションを制御する、それはまだ時間がかかるだろう、と私はまだ解決方法を知らない。ご回答有難うございます。 – TNA

0

あなたは上の作業を行う方法についてさまざまなオプションがいくつかありバックグラウンドスレッド。 backgroundworker(若干古い)または.NET 4.0 Tasks(Task Parallel Libraryの一部)を使用することができます。すべてのデータを新しいコレクションにロードし、一度にGUIスレッドへの更新を呼び出すか、バッチでアイテムをロードし、GUIに数回ラウンドを呼び出すかどうかを決定する必要があります

関連する問題