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 メソッドが 2 回目に実行された後、最初のコレクションが完全に追加されていない場合、DataGrid には最初のコレクションの一部と 2 番目のコレクション全体が含まれます。

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

DispatcherOperation を中止しようとしましたが、Items プロパティへの連絡先の追加が停止しません。

オブジェクトを DataGrid ItemsSource に追加する正しい方法を教えてください。

4

2 に答える 2

1

リスト内のすべての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));
    }
}
于 2012-04-27T04:55:30.837 に答える
1

あなたのUpdate(contactList1)メソッドDispatcher.BeginInvoke()では、contactList1 のすべてのアイテムに対して開始しますが、入力Update(contactList2)すると、完全な foreach ではなく単一の .LastOperation を 1 回だけ中止します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);
}
于 2012-04-26T17:35:26.247 に答える