简体   繁体   中英

How to bind a collection to a ListView in WPF

I have a program that searches a directory for files matching certain criteria. This search process takes a long time, so I have to call it asynchronously. When the search algorithm finds a file, it triggers an event. My MainWindow instance listens for this event and needs to update the GUI. How can I bind these "added" files to a ListView ? I figured that I could use an ObservableCollection<FileInfo> instance, but I can't figure out how to bind it.

I've stripped out all of the irrelevant controls and code. Here are the two relevant files.

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

Here is a simple example

Your 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>

Your Code Behind

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

If you run this problem you will notice that the listbox updates every half a second with a new item. Basically the key thing to note is that the ObservableCollection can only be updated from the UI thread so if you refactor the above code you need need to somehow use the Dispatcher of the current UI thread to update it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM