2013-04-01 4 views
6

Ich habe ein Programm, das ein Verzeichnis nach Dateien durchsucht, die bestimmte Kriterien erfüllen. Dieser Suchvorgang dauert eine lange Zeit, also muss ich es asynchron aufrufen. Wenn der Suchalgorithmus eine Datei findet, wird ein Ereignis ausgelöst. Meine MainWindow Instanz wartet auf dieses Ereignis und muss die GUI aktualisieren. Wie kann ich diese "addierten" Dateien an eine ListView binden? Ich dachte, dass ich eine ObservableCollection<FileInfo> Instanz verwenden könnte, aber ich kann nicht herausfinden, wie man es bindet.So binden Sie eine Auflistung an eine ListView in WPF

Ich habe alle irrelevanten Steuerelemente und Code entfernt. Hier sind die zwei relevanten Dateien.

MainWindow.xaml:

<Window x:Class="Example.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="CR Search" Height="395" Width="525"> 
    <Grid> 
     <ListView x:Name="Results"> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn Header="Filename"/> 
        <GridViewColumn Header="Directory"/> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </Grid> 
</Window> 

MainWindow.xaml.cs:

using System.IO; 
using System.Threading.Tasks; 

public partial class MainWindow 
{ 
    private SearchLogic _backgroundSearch; 

    private async void Search(object sender, RoutedEventArgs e) 
    { 
     // TODO: clear Results 

     _backgroundSearch = new SearchLogic("", new DirectoryInfo("C:\")); 
     _backgroundSearch.FileAdded += FileAdded; 

     await Task.Run(new Action(_backgroundSearch.Search)); 
    } 

    private void FileAdded(object sender, FileAddedEventArgs eventArgs) 
    { 
     // TODO: add eventArgs.File to Results 
     // eventArgs.File is an instance of FileInfo 
    } 
} 

Antwort

12

Hier ist ein einfaches Beispiel

Ihre XAML

<Window x:Class="WpfApplication10.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" 
     Width="525" 
     Height="350" 
     Loaded="Window_Loaded"> 
    <Grid> 
     <ListBox ItemsSource="{Binding FileNames}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Vertical"> 
         <Label>Name</Label> 
         <TextBlock Text="{Binding Name}"/> 
         <Label>Modified</Label> 
         <TextBlock Text="{Binding LastModified}"/>       
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </Grid> 
</Window> 

Ihr Code hinter

public partial class MainWindow : Window 
{ 
    public class FileInfo 
    { 
     public string Name { get; set; } 
     public DateTime LastModified { get; set; } 
     public FileInfo(string name) 
     { 
      Name = name; 
      LastModified = DateTime.Now; 
     } 
    } 

    ObservableCollection<FileInfo> mFileNames = new ObservableCollection<FileInfo>(); 

    public ObservableCollection<FileInfo> FileNames 
    { 
     get 
     { 
      return mFileNames; 
     } 
    } 

    public MainWindow() 
    { 
     DataContext = this; 
     InitializeComponent(); 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     ThreadPool.QueueUserWorkItem((x) => 
      { 
       while (true) 
       { 
        Dispatcher.BeginInvoke((Action)(() => 
        { 
         mFileNames.Add(new FileInfo("X")); 
        })); 
        Thread.Sleep(500); 
       } 
      }); 
    } 
} 

Wenn Sie dieses Problem laufen, werden Sie feststellen, dass die listbox jede halbe Sekunde mit einem neuen Update aktualisiert. Grundsätzlich ist zu beachten, dass die ObservableCollection nur über den UI-Thread aktualisiert werden kann. Wenn Sie also den obigen Code umgestalten, müssen Sie den Dispatcher des aktuellen UI-Threads irgendwie verwenden, um ihn zu aktualisieren

+0

Ich habe das Threading Situation herausgefunden. Was ist mit Objekten in der ObservableCollection? Zum Beispiel eine Sammlung von 'FileInfo'-Objekten. Wie binde ich den Dateinamen und sein Verzeichnis an Spalten in der 'ListView'? –

+0

Ich habe gerade meine Antwort aktualisiert. Wenn Ihre 'FileInfo' veränderbar ist und Sie ihre Eigenschaften ändern, nachdem Sie sie zur Liste hinzugefügt haben, müssen Sie' INotifyPropertyChanged' implementieren, so dass die UI Updates –

+0

Ich benutze die ['System.IO.FileInfo' Klasse] (http : //msdn.microsoft.com/en-us/library/system.io.fileinfo.aspx). Mit dem gesagt, gibt es einen Grund, warum Sie eine "ListBox" anstelle einer "ListView" verwenden? –