Отправить данные между классом и формой? - PullRequest
0 голосов
/ 08 апреля 2009

На днях я спросил , как создать окно сообщения в вашем классе , но в одном из ответов было сказано, что это неправильный подход. Я понимаю, что это потому, что это действительно побеждает точку класса.

Моя программа читает слово за словом из строкового файла и проверяет, есть ли каждое слово в базе данных. Я хочу поместить каждое слово, не найденное в ListBox в форме, которая может иметь несколько вариантов выбора.

Как отправить эти данные обратно в форму каждый раз, когда найдено новое слово?

Ответы [ 4 ]

1 голос
/ 08 апреля 2009

Если у класса есть ссылка на форму, он может просто обновить форму напрямую.

someForm.SomeListBox.Items.Add(someWord);

Если форма имеет ссылку на класс, вы можете сделать так, чтобы класс вызвал событие, подобное

public delegate string WordNotFoundHandler(string word);
public WordNotFoundHandler event WordNotFound ;

и иметь форму обработки этого события

theClass.WordNotFound += AddItemToListBox

void AddItemToListBox(string word)
{
someListBox.Items.Add(word);
}

преимущество выполнения этого способа вместо одного огромного вызова, который возвращает все слова, состоит в том, что оно обеспечивает более быстрое время отклика пользовательского интерфейса, особенно когда это делается отдельным потоком

1 голос
/ 08 апреля 2009

Я предлагаю вам сделать метод примерно так:

/* ... */

public IEnumerable<string> FindMissingWords(
                               string fileName, IEnumerable<string> toSearch)
{
    List<string> missingWords = new List<string>();

    // todo: the appropriate code for looking up strings in the file, using 
    // the filename and the strings that we passed into the function.

    // if you find one, add it to missingWords

    return missingWords;
}

Затем вызовите этот метод из вашей формы и добавьте каждую строку, которую он возвращает, в ваш ящик.

(Если вы не знакомы с IEnumerable, не беспокойтесь - это просто интерфейс, который определяет последовательность вещей, например, массив или список. Вы можете передать массив строк вместо этого будет немного менее точным.)

0 голосов
/ 08 апреля 2009

Вы не хотите связывать вашу форму с классом, который ищет и находит слова из файла. Вот решение на основе событий

По сути, вам нужно выставить в классе событие, которое читает и находит слова из файла (для иллюстрации я назвал его WordFinder).

WordFinder предоставляет событие с именем WordFound, которое возникает при обнаружении нового слова.

public class WordFinder
{
    public event EventHandler<WordFoundEventHandler> WordFound = delegate { };
    public event EventHandler NoWordsFound = delegate { };

    protected virtual void OnWordFound(WordFoundEventHandler e)
    {
        var wordFoundHandler = WordFound;
        wordFoundHandler(this, e);
    }

    private void OnNoWordsFound(EventArgs e)
    {
        var noWordsFoundHandler = NoWordsFound;
        noWordsFoundHandler(this, e);
    }

    public void FindWords(string fileName)
    {
        //.. read file and find word
        //.. When a word is found,
        OnWordFound(new WordFoundEventHandler(foundWord));

        // Keep a counter somewhere and check if any words has been found, 
        // if no words are found, then raise "NoWordsFoundEvent"
        OnNoWordsFound(EventArgs.Empty);
    }
}

public class WordFoundEventHandler : EventArgs
{
    public string FoundWord { get; private set; }

    public WordFoundEventHandler(string foundWord)
    {
        FoundWord = foundWord;
    }
}

Теперь ваша форма будет просто регистрироваться на событие WordFinder и добавлять новый элемент при обнаружении нового слова.

public partial class Form1 : Form
{
    private readonly WordFinder _WordFinder;

    public Form1()
    {
        InitializeComponent();

        _WordFinder = new WordFinder();
        _WordFinder.WordFound += WordFinder_WordFound;
        _WordFinder.NoWordsFound += WordFinder_NoWordsFound;
    }

    private void WordFinder_WordFound(object sender, WordFoundEventHandler e)
    {
        // Add item to the list here.
        foundWordsListBox.Items.Add(e.FoundWord);
    }

    private void WordFinder_NoWordsFound(object sender, EventArgs e)
    {
        MessageBox.Show("No words found!");
    }

    private void findWordsButton_Click(object sender, EventArgs e)
    {
        _WordFinder.FindWords(/* pass file name here */);
    }
}
0 голосов
/ 08 апреля 2009

Вот что я бы сделал (или подобное):

    bool done = false;
    while(true)
    {
        string foundstring;
        done = searchforstring(out foundstring);
        if(done)
            break;
        // Not done, so take what we found and add it to the listbox
        this.BeginInvoke(new Action<string>(delegate(string input)
            { this.listBox.BeginUpdate(); this.listBox.Items.Add(input); this.listBox.EndUpdate(); }),
            new object[] { foundstring });

        }

Подставьте имя вашего элемента управления списком, и я думаю, что это будет работать. Или вы можете разбить анонимный метод на его собственный объект. Идея состоит в том, что каждый раз, когда вы находите новую строку, вы отправляете работника для выполнения обновления в «главном потоке приложения» (отсюда вызов BeginInvoke ()). Я не ПОЛНОСТЬЮ предъявляю иск, если вызовы begin / endUpdate () строго необходимы, но они могут быть.

Очевидно, как вы ПОЛУЧАЕТЕ строки, зависит от вас, но это должен быть способ получить его в списке на лету, если ваше приложение является многопоточным. Если он не многопоточный, прямой Invoke () (вместо BeginInvoke) должен работать для немедленного обновления списка, но это, вероятно, ухудшит производительность вашего поиска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...