English 中文(简体)
在类和表单之间发送数据?
原标题:
  • 时间:2009-04-07 20:18:48
  •  标签:

前几天,我问如何在课堂上创建一个消息框,但其中一个答案是这不是正确的方法。我理解这是因为它确实违背了课堂的要点。

我的程序从字符串文件中逐字逐句地读取,并检查每个单词是否都在数据库中。我想把找不到的每个单词都放在表单上的ListBox中,它可以有多个选项。

每次发现新单词时,我如何将数据发送回表单?

最佳回答

我建议你做一个这样的方法:

/* ... */

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,请不要担心,它只是一个定义一系列事物的接口,比如数组或列表。您可以传递一个字符串数组,但精度会稍低。)

问题回答

如果类有对表单的引用,则它可以直接更新表单。

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

这样做的好处是,它提供了更快的ui响应时间,尤其是当由单独的线程完成时,而不是一个返回所有单词的巨大调用

这是我要做的(或类似的):

    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()调用是绝对必要的,我不会完全起诉,但它们可能是必要的。

显然,如何获取字符串取决于您自己,但假设您的应用程序是多线程的,那么这应该是将字符串快速放入列表框的方法。如果它不是多线程的,那么直接调用()(而不是BeginInvoke)应该可以立即更新列表框,但这可能会降低搜索性能。

You do not want to couple your form with the class that searches and find words from a file. Here is an Event-based solution

Basically what you have to do is to expose an event in the class that reads and find words from a file (I named it as WordFinder for an illustration.)

WordFinder exposes an event called WordFound that is raised when a new word is found.

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




相关问题
热门标签