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 的正确方法吗?

4

2 回答 2

1

在您的Update(contactList1)方法中,您Dispatcher.BeginInvoke()为contactList1 中的每个项目启动一个,但如果您输入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);
}
于 2012-04-26T17:35:26.247 回答
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 回答