我知道已经有几种类型的问题了。但是我的例子似乎有些不同。此外,WPF和ObservableCollections对我来说仍然是非常新的。因此,将不胜感激。我的电网正在更新,但只有在所有" listoffiles"迭代后才进行更新。我希望它在每个文件找到后更新网格。
注意:我只使用thread.sleep来使过程更可见
xaml
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button x:Name="btnAdd" Content="Add" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="btnAdd_Click"/>
<DataGrid x:Name="dgFiles" HorizontalAlignment="Left" Margin="90,10,0,0" VerticalAlignment="Top" Height="300" Width="417"/>
</Grid>
c#
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Threading;
using System.Windows;
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public class FilesFound
{
public string FileName { get; set; }
public string FileCount { get; set; }
}
private ObservableCollection<FilesFound> file = new ObservableCollection<FilesFound>();
public MainWindow()
{
InitializeComponent();
dgFiles.ItemsSource = file;
file.CollectionChanged += this.OnCollectionChanged;
}
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ObservableCollection<FilesFound> obsSender = sender as ObservableCollection<FilesFound>;
NotifyCollectionChangedAction action = e.Action;
}
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
string[] listOfFiles = Directory.GetFiles(@"C:TEST", "*.*", SearchOption.AllDirectories);
int count = 0;
foreach (var file in listOfFiles)
{
if (file.Contains("CLIENT"))
{
count++;
FilesFound f = new FilesFound();
f.FileName = file;
f.FileCount = count.ToString();
this.file.Add(f);
Thread.Sleep(500);
}
}
}
}
}
您应该在背景线程上执行循环,但在UI线程上更新数据observablecollection,因为单个线程不能同时执行两件事。
启动背景线程的最简单方法是使用任务。然后,您可以使用调度程序将访问observableCollection访问UI线程的任何调用。尝试以下操作:
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
string[] listOfFiles = Directory.GetFiles(@"C:TEST", "*.*", SearchOption.AllDirectories);
int count = 0;
foreach (var file in listOfFiles)
{
if (file.Contains("CLIENT"))
{
count++;
FilesFound f = new FilesFound();
f.FileName = file;
f.FileCount = count.ToString();
Dispatcher.BeginInvoke(new Action(() => this.file.Add(f)));
Thread.Sleep(500);
}
}
});
}
正如您在对帖子的评论中所说的,使用异步/等待等待UI线程(这是我以前使用过的方法 - 无论如何)。
因此您需要类似的东西:
private async void btnAdd_Click(object sender, RoutedEventArgs e)
{
string[] listOfFiles = Directory.GetFiles(@"C:TEST", "*.*", SearchOption.AllDirectories);
await Task.Run(() =>
{
int count = 0;
foreach (var file in listOfFiles)
{
if (file.Contains("CLIENT"))
{
count++;
FilesFound f = new FilesFound();
f.FileName = file;
f.FileCount = count.ToString();
this.file.Add(f);
Thread.Sleep(500);
}
}
});
}
作为附带说明,您可能应该使用MVVM和ICommand接口查找,以分开UI和业务逻辑。