1

我正在开发一个 Wpf 应用程序,它使用 EF 从数据库中检索数据。

我有一些 ListView 控件,其中填充了数据库的一些表,因此为了防止在检索数据时阻塞 UI,我执行以下操作:

        Task tsk = Task.Factory.StartNew(() =>
        {
            ItemsSource = Database.SomeTable();
        });

ItemsSource 变量是绑定到 ListView 的 ItemsSource 属性的 ObservableCollection。

事实是,正如预期的那样,在加载数据时 UI 保持响应。我的问题是 ListView 在加载所有数据之前都是空的。所以我想逐个元素地查看 ListView 中出现的元素。有没有办法做到这一点??我试过哪个 foreach 循环没有运气。

提前致谢。

4

2 回答 2

4

这可以通过使用从您的任务调用的 Disptacher 的 BeginInvoke 方法将新元素添加到您的可观察集合中来完成。就像是:

//MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <ListView ItemsSource="{Binding MyList}" Grid.Row="0" />
        <Button Content="Load" Click="OnLoadClicked" Grid.Row="1" Height="30" />
    </Grid>
</Window>

//MainWindow.xaml.cs

using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private VM _vm = new VM();
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = _vm;
        }

        private void OnLoadClicked(object sender, RoutedEventArgs e)
        {
            Load10Rows();            
        }

        private void Load10Rows()
        {
            Task.Factory.StartNew(() =>
                {
                    for (int i = 0; i < 10; i++)
                    {
                        Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                _vm.MyList.Add(DateTime.Now.ToString());
                            }), DispatcherPriority.Background);
                        // Just to simulate some work on the background
                        Thread.Sleep(1000);
                    }
                });
        }
    }

    public class VM
    {
        private ObservableCollection<string> _myList;
        public VM()
        {
            _myList = new ObservableCollection<string>();
        }

        public ObservableCollection<string> MyList
        {
            get { return _myList; }
        }
    }
}

如果您有大量记录,您可能需要对其进行分块,否则只需为每条记录调用 Disptacher。

于 2013-10-25T04:33:43.993 回答
1

也许使用Task.Delay允许 UI 在 foreach 中添加下一个项目之前呈现更改将起作用

例子:

private async Task AddItems()
{
    foreach (var item in Database.SomeTable())
    {
        ItemsSource.Add(item);
        await Task.Delay(1);
    }
}
于 2013-10-25T04:03:33.693 回答