2013-11-02 45 views
1

我高舉兩個用戶控件。 第一個包含一個ItemsControl,我必須用我的第二個用戶控件動態填充它。第二個用戶控件可能會遞歸地包含另一個ÌtemsControl,所以初始化控件非常繁重。如何在另一個線程中初始化繁重的控件?

這裏是我做了SubControl

public sealed partial class SubControl : UserControl 
{ 
    public SubControl(ModelA item) 
    { 
     this.InitializeComponent(); 
     this.DataContext = item; 

     //if the current item has child items, add them to the ItemsControl: 
     if(item.SubItems != null) 
     { 
      BuildUI(item.SubItems); 
     } 
    } 

    private void BuildUI(List<AbstractModel> data) 
    { 
     foreach(var item in data) 
     { 
      var dataItem = item as ModelA; 
      //we only want item of type ModelA in our ItemsControl: 
      if(dataItem != null) 
      { 
       SubElements.Items.Add(new SubControl(dataItem)); 
      } 
     } 
    } 
} 

現在,這裏是我寫的第一個用於其ItemsControl(稱爲Elements)包含一組這些SubControlMainControl

public sealed partial class MainControl : UserControl 
{ 
    public MainControl(List<AbstractModel> data) 
    { 
     this.InitializeComponent(); 
     BuildUI(data); 
    } 

    private void BuildUI(List<AbstractModel> data) 
    { 
     foreach(var item in data) 
     { 
      var dataItem = item as ModelA; 
      if(dataItem != null) 
      { 
       Elements.Items.Add(item); 
      } 
     } 
    } 
} 

在構建「樹」時,我注意到了用戶界面的小凍結,但是我目前正在使用功能非常強大的計算機。我希望應用程序即使在Windows Surface RT等較小設備上也能順利運行。所以我改變了MainControl代碼:

public sealed partial class MainControl : UserControl 
{ 
    public MainControl(List<AbstractModel> data) 
    { 
     this.InitializeComponent(); 
     BuildUI(data); 
    } 

    private async void BuildUI(List<AbstractModel> data) 
    { 
     var list = new List<SubControl>(); 
     await Task.Run(() => 
     { 
      foreach(var item in data) 
      { 
       var dataItem = item as ModelA; 
       if(dataItem != null) 
       { 
        list.Add(new SubControl(dataItem)); 
       } 
      } 
     }); 
     foreach(var item in list) 
     { 
      Elements.Items.Add(item); 
     } 
    } 
} 

的想法是建立所有SubControl在不同的線程,因此UI不堵塞,而當所有的用戶控件已被初始化,我們將它們添加到ItemsControlMainControl

然而,這並不因爲數據的編組工作,即使不是一個單一的SubControl是實際存在的UI!它在構建SubControl時崩潰,這很奇怪,因爲它對實際的UI沒有任何影響;他們只是添加到臨時List

什麼可以在後臺任務來構建這些用戶控件所以UI不會凍結一招?

回答

4

Windows用戶界面非常單線程的。必須創建每個UI控件必須,並且只能從單個線程使用。這是沒有辦法的。

因此,它的時間去思考解決方案稍有不同。創建幾十個控件是沒有問題的;用戶界面將處理得很好。您正在討論將數百或數千個項目添加到列表控件,而這只是一個不可用的用戶界面。所以正確的解決方案是重新考慮你的UI設計。也許你可以把結果分成不同的類別。

如果您已經考慮了您的UI設計,並且確定要向用戶顯示數百或數千個項目,那麼答案就是使用virtualization。這不僅僅是一個簡單的foreach循環的代碼更難,但它是有效顯示大量數據的唯一方法。

-1

有很多方法可以做到這一點。

您可以使用此工作流程:

  • 實現一個事件處理程序,即上調initialiazation完成。
  • 顯示空MainControl與說「加載」
  • 建立另一個線程所有的UI
  • 在建的所有用戶界面,提高終點事件
  • 一個監聽器,本次活動將子控件添加到您的MainControl

[...],因爲它沒有實際的UI任何影響;他們只是被添加到一個臨時列表

順便說一句:你的代碼確實崩潰了,因爲你在一個異步方法中添加了控件,這實際上是一個非GUI線程。所以你錯了你的主張。

+2

您建議在「另一個線程」上構建UI,而您通過注意到無法在非UI線程上添加控件來自相矛盾。 –

+0

您不能在另一個線程中「構建UI」。 –

相關問題