2016-12-30 27 views
1

すでにこれらのタイプの質問がいくつかあります。しかし私の例は少し違っているようです。また、WPFとObservableCollectionsはまだ私にとって非常に新しいです。だから、助けていただければ幸いです。私のグリッドは更新されていますが、それがすべての "listOfFiles"を反復した後にのみ更新されます。見つかった各ファイルの後にグリッドを更新したいと思います。ObservableCollectionに問題がなく、各変更でUIが更新されない

注:あなたがあなたの中で言ったように、私は唯一の

プロセスをより見やすくするために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); 
       } 
      } 
     } 
    } 
} 
+1

'foreach'ループはUIスレッドで実行され、終了するまでブロックします。 'Thread.Sleep()'を呼び出すと、さらに悪化します。 [TPL](https://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx)または[BackgroundWorker](https://msdn.microsoft.com/)を参照してください。 en-us/library/system.componentmodel.backgroundworker(v = vs.110).aspx)。 – Clemens

+1

この操作はUIスレッドで実行しています。つまり、UIがその操作が完了するまで更新する機会はありません。 – Evk

+0

私はObservableCollectionsを使ってこれを軽減すると考えました。 – JimDel

答えて

1

バックグラウンドスレッドでループを実行する必要がありますが、データスレッドObservableCollectionをUIスレッドで更新する必要があります.1つのスレッドが2つのことを同時に行うことはできないからです。

バックグラウンドスレッドを開始する最も簡単な方法は、タスクを使用することです。その後、ディスパッチャを使用して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); 
      } 
     } 
    }); 
} 
1

をのThread.sleepを使用しています投稿にコメントするには、async/awaitを使用してUIスレッドを解放する必要があります(これは以前使用した方法ですly - とにかく)。

だからあなたのようなものが必要です。注意点として

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); 
        } 
       } 
      }); 
    } 

を、あなたはおそらく、あなたのUIとビジネスロジックを分離するためにMVVMとのICommandインターフェイスを使用して調べる必要があります。

関連する問題