1

我想在線程中向DataGrid添加項目。調度員:中止調度程序操作

我有我的用戶控制視圖模型:

public class Contact 
{ 
    public string Name { get; set; } 
    public string Phone { get; set; } 
} 

public class ContactGridViewModel 
{ 
    public ContactGridViewModel() 
    { 
     Items = new ObservableCollection<Contact>(); 
    } 

    public ObservableCollection<Contact> Items { get; private set; } 

    public Dispatcher Dispatcher 
    { 
     get { return Dispatcher.CurrentDispatcher); } 
    } 
    private DispatcherOperation LastOperation { get; set; } 

    public void Update(IEnumerable<Contact> contacts) 
    { 
     if (LastOperation != null) LastOperation.Abort(); 

     Items.Clear(); 
     foreach (var item in contacts) 
      LastOperation = Dispatcher.BeginInvoke(
        DispatcherPriority.Background, 
        new ParameterizedThreadStart(o => Items.Add(o))), 
        item); 
    } 
} 

有標記示例:

<!--DataContext="{Binding ContactGridViewModel}--> 

<DataGrid ItemsSource="{Binding Items, Mode=OneWay}"> 
    <DataGrid.Columns> 
    <DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" /> 
    <DataGridTextColumn Header="Phone" Binding="{Binding Path=Phone}" /> 
    </DataGrid.Columns> 
</DataGrid> 

後更新方法執行第二次,如果第一次收集不完全加入, DataGrid將包含第一個集合和第二個集合的一部分。

// contactList1 and contactList2 are IEnumerable<Contact> objects 
Model.Update(contactList1); 
Model.Update(contactList2); 

我嘗試中止DispatcherOperation,但它不停止將聯繫人添加到Items屬性中。

你能告訴我將對象添加到DataGrid ItemsSource的正確方法嗎?

+0

Abort()返回什麼?首先還是最後一部分的第一部分仍然存在? – LPL 2012-04-26 15:25:34

+0

@LPL它返回true。第一次收集的最後部分仍然存在。 – ebashmakov 2012-04-26 17:07:24

回答

2

你應該收集列表中的所有DispatcherOpretations,然後放棄他們。

public class ContactGridViewModel 
{ 
    public ContactGridViewModel() 
    { 
     Items = new ObservableCollection<Contact>(); 
     LastOperations = new List<DispatcherOperation>(); 
    } 

    public ObservableCollection<Contact> Items { get; private set; } 
    private ICollection<DispatcherOperation> LastOperations { get; set; } 

    public Dispatcher Dispatcher 
    { 
     get { return Dispatcher.CurrentDispatcher); } 
    } 

    private void StopUpdating() 
    { 
     foreach (var operation in LastOperations) 
     { 
      operation.Abort(); 
     } 
     LastOperations.Clear(); 
    } 

    public void Update(IEnumerable<Contact> contacts) 
    { 
     StopUpdating(); 

     Items.Clear(); 
     foreach (var item in contacts) 
      LastOperations.Add(Dispatcher.BeginInvoke(
        DispatcherPriority.Background, 
        new ParameterizedThreadStart(o => Items.Add(item))), 
        item)); 
    } 
} 
1

在你Update(contactList1)方法您contactList1每個項目開始Dispatcher.BeginInvoke(),但如果你輸入Update(contactList2)你中止只有一次LastOperation,這是不完整的foreach而是一個單一Items.Add()

嘗試這樣的事情(未測試):

public void Update(IEnumerable<Contact> contacts) 
{ 
    if (LastOperation != null) LastOperation.Abort(); 

    Items.Clear(); 
    LastOperation = Dispatcher.BeginInvoke(
     DispatcherPriority.Background, 
     new ParameterizedThreadStart(o => { foreach (var item in o) Items.Add(item); }), 
     contacts); 
} 
+0

必須等到所有項目都會添加 – ebashmakov 2012-04-27 04:50:48

+0

謝謝,您已將我帶入正確的解決方案 – ebashmakov 2012-04-27 04:57:44