0

我正在開發一個適用於SharePoint的Silverlight應用程序,並希望從列表中獲取ListItems。我知道我需要異步查詢以避免阻塞UI線程。通常我使用ExecuteQueryAsync,但是由於我喜歡將結果設置爲DataGrid源,因此無法工作。如何在Silverlight 4中異步調用方法?

如何異步調用GetItemsFromList方法,並將結果設置爲DataGrid源而不會產生太多的代碼開銷? (拉姆達?)

SharePointHelper類:

public static ListItemCollection GetItemsFromList(string name) 
{ 
    var context = ClientContext.Current; 
    var targetList = context.Web.Lists.GetByTitle("ListName"); 

    CamlQuery camlQuery = new CamlQuery(); 
    camlQuery.ViewXml = string.Format("<View><Query><Where><Eq><FieldRef Name='Title'/><Value Type='Text'>{0}</Value></Eq></Where></Query>RowLimit>4</RowLimit></View>", 
             name); 

    ListItemCollection collListItems = targetList.GetItems(camlQuery); 
    context.ExecuteQuery(); 

    return collListItems; 
} 

UI類:

private void SetDataGridItemSource() 
{ 
    dataGrid.Source = GetItemsFromList("name"); 
} 

我現在已經實現從肖恩Kendrot解決方案:

BackgroundWorker worker = new BackgroundWorker(); 
worker.DoWork += (sender, args) => 
{ 
    args.Result = SharePointHelpers.GetItemsFromList("name"); 
}; 
worker.RunWorkerCompleted += (s, e) => dataSource.Source = e.Result as ListItemCollection; 
worker.RunWorkerAsync(); 

回答

1

我不熟悉的SharePoint(或甚至的SharePoint爲此事)的ClientContext類,但我沒有看到任何docs異步方法。如果此通話費用很高,您可以將電話打包爲BackgroundWorker。 BackgroundWorker將執行查詢,您可以返回結果。您將無法按照您所描述的方式分配Source,但需要在工作人員完成時設置Source。

private void SetDataGridItemSource() 
    { 
     BackgroundWorker worker = new BackgroundWorker(); 
     worker.DoWork += WorkerOnDoWork; 
     worker.RunWorkerCompleted += WorkerOnRunWorkerCompleted; 
     worker.RunWorkerAsync("name");  
    } 

    private void WorkerOnDoWork(object sender, DoWorkEventArgs args) 
    { 
     if(args.Argument != null) 
     { 
      string name = args.Argument.ToString(); 
      var context = ClientContext.Current; 
      var targetList = context.Web.Lists.GetByTitle("ListName"); 

      CamlQuery camlQuery = new CamlQuery(); 
      camlQuery.ViewXml = string.Format("<View><Query><Where><Eq><FieldRef Name='Title'/><Value Type='Text'>{0}</Value></Eq></Where></Query>RowLimit>4</RowLimit></View>", 
               name); 

      ListItemCollection collListItems = targetList.GetItems(camlQuery); 
      context.ExecuteQuery(); 

      args.Result = collListItems; 
     } 
    } 

    private void WorkerOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs args) 
    { 
     dataGrid.Source = args.Result as ListItemCollection; 
    } 
+0

這將工作,但對於此解決方案,我需要爲每個我喜歡打電話的方法添加一個BackgroundWorker,並且必須註冊該事件。我希望像@丹Wray嘗試更好的解決方案;-) – jwillmer 2012-08-13 16:59:29

+0

使用回調和訂閱事件本質上是一回事。由於這些方法看起來不是異步的,所以您需要使它們異步。 BackgroundWorker使這成爲可能。如果您不喜歡擁有完整的方法,只需將事件訂閱更改爲:worker.RunWorkerCompleted + =(s,e)=> dataGrid.Source = e.Result as ListItemCollection; – 2012-08-13 18:36:37

0

像這樣的事情?

public delegate void ItemsLoadedCallback(IEnumerable<object> Entities); 
public static void GetItemsFromList(string name, ItemsLoadedCallback Callback) 
{ 
    // codesnip 

    // Do async thing, on return call: 
    if (Callback != null) 
    { 
     Callback(collListItems); 
    } 
} 


private void SetDataGridItemSource() 
{ 
    GetItemsFromList("name", (items) => dataGrid.Source = items); 
} 
+0

獲取此錯誤:調用的方法或屬性可能會阻塞UI線程,並且不允許。請使用後臺線程來調用方法或屬性,例如使用System.Threading.ThreadPool.QueueUserWorkItem方法來調用方法或屬性。 – jwillmer 2012-08-13 16:54:23

+0

我完全不熟悉Sharepoint。我的印象是,你可以在某個地方使用「ExecuteQueryAsync」方法來異步執行你的查詢,我上面顯示的代碼只能真實地顯示你如何捕獲這個異步調用的結果並將它返回給你的原始代碼通過委託調用方法。如果你不能以本地方式異步執行操作,你可能會使用後臺工作者來做到這一點,如Shawn的解決方案所示。 – 2012-08-14 07:47:32