WPF application depending on large file
This is actually a nice example of how re-writing an application using MVVM can make life easier. It looks like you have the wrong idea about MVVM (your code should not be in the code behind). As a starting point, you would need an empty MVVM application with a main viewmodel and view, and know how to set up data binding and property changed events. If you haven't done this before, I would recommend taking a look at MVVM light which is a small framework that can get you up and running quickly.

The idea is that your view and viewmodel should not care where the messages are coming from - that is not their concern. This is in line with SRP and means that you can change how you read from the files (or read from somewhere else entirely) without touching any code in your V and VM layers. I would suggest starting with something like this:

ViewModel

public class MainViewModel : ViewModelBase
{
    private IMessageRepository _messageRepository;

    public MainViewModel(IMessageRepository messageRepository)
    {
        _messageRepository = messageRepository;
        FilteredMessages = _messageRepository.GetMessages();
    }

    // This will be bound to the search Button via a command
    public void FilterMessages(string searchString)
    {
        var messages = _messageRepository.GetMessages();
        FilteredMessages = messages.Where(m =&gt; m.Contains(searchString, StringComparison.OrdinalIgnoreCase))
    }

    // This will need to be bound to the ListBox and raise PropertyChangedEvents when set
    public IEnumerable&lt;Message&gt; FilteredMessages { get; private set; }
}


Model

public interface IMessageRepository
{
    IEnumerable&lt;Message&gt; GetMessages();
}

public abstract class FileMessageRepository : IMessageRepository
{
    protected readonly string FilePath;

    protected FileMessageRepository(string filePath)
    {
        FilePath = filePath;
    }

    public abstract IEnumerable&lt;Message&gt; GetMessages();

    protected Message BuildMessage(string line)
    {
        ...
    }
}

public class LazyFileMessageRepository : FileMessageRepository
{
    public LazyFileMessageRepository(string filePath) : base(filePath)
    {
    }

    public override IEnumerable&lt;Message&gt; GetMessages()
    {
        // This will read from the file as it is enumerated
        return File.ReadLines(FilePath).Select(BuildMessage);
    }
}

public class EagerFileMessageRepository : FileMessageRepository
{
    private Message[] _cachedMessages;

    public EagerFileMessageRepository(string filePath) : base(filePath)
    {
    }

    public override IEnumerable&lt;Message&gt; GetMessages()
    {
        // This will read from the file once (slow) and keep the result in memory
        return _cachedMessages ?? (_cachedMessages = File.ReadAllLines(FilePath).Select(BuildMessage).ToArray());
    }
}


With this implementation you are free to choose which IMessageRepository you use, and can carry out performance/profiling tests as required.