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> 

После метода Update выполняется второй раз, и если первая коллекция полностью не добавил, DataGrid будет содержать часть первой коллекции и полную вторую коллекцию.

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

Я пытаюсь прервать DispatcherOperation, но это не прекращает добавлять контакты в свойство Items.

Не могли бы вы рассказать мне правильный метод добавления объектов в DataGrid ItemsSource?

+0

Что возвращает Abort()? А какая часть первой коллекции осталась, первая или последняя? – LPL

+0

@LPL возвращает true. Последняя часть первой коллекции осталась. – ebashmakov

ответ

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) вы начинаете Dispatcher.BeginInvoke() для каждого элемента в contactList1, но если вы входите Update(contactList2) вы прерываете только один раз LastOperation, который не является полным Еогеаспом но одного 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

+0

спасибо, вы привели меня к правильному решению – ebashmakov

Смежные вопросы