アウトラインプロセッサーに検索機能を追加します。検索する場所も現在選択されているノードだけ、ファイル全体、選択されているノードの配下など選択できるようにします。また前回の検索結果から絞り込み検索もできるようにします。
DataクラスのなかにはRichDataプロパティがあり、このなかにRtfプロパティとTextプロパティがあります。Textプロパティを調べれば検索している文字列があるかどうかわかります。
下は検索結果を表示するフォームです。左がリストボックス、右はリッチテキストボックスになっていて、ここからも編集が可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class Form1 : Form { private void SearchToolStripMenuItem1_Click(object sender, EventArgs e) { SearchString(); } void SearchString() { TreeNodeEx nodeEx = syncTreeViewEx1.SelectedNode; if (nodeEx == null) return; SaveToMoromy(); SearchForm form = new SearchForm(); form.tree = syncTreeViewEx1; Task.Run(() => { form.ShowDialog(); }).ConfigureAwait(false); } } |
つぎにSearchFormを表示します。SearchFormの検索をクリックすると検索が開始され、プログレスバーでどれくらい処理が進んだかもわかります。
1 2 3 4 5 6 7 8 9 10 |
public partial class SearchForm : Form { public SearchForm() { InitializeComponent(); } public bool IsCancel = false; public SyncTreeViewEx tree = null; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public partial class SearchForm : Form { private void buttonStop_Click(object sender, EventArgs e) { IsCancel = true; } private void buttonSearch_Click(object sender, EventArgs e) { string str = textBox1.Text; if (str == "") { MessageBox.Show("検索文字列が入力されていません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } Task.Run(() => { if (radioButtonAll.Checked) SearchAll(tree, tree.SelectedNode, str); else if (radioButtonChildren.Checked) SearchChildren(tree, tree.SelectedNode, str); else if (radioButtonOnly.Checked) SearchOnly(tree, tree.SelectedNode, str); }).ConfigureAwait(false); } void SearchAll(SyncTreeViewEx tree, TreeNodeEx nodeEx, str) { List<TreeNodeEx> treeNodeExes = tree.GetTreeNodeExs(null); SearchNodes(treeNodeExes, str); } void SearchChildren(SyncTreeViewEx tree, TreeNodeEx nodeEx, str) { List<TreeNodeEx> treeNodeExes = tree.GetTreeNodeExs(nodeEx); SearchNodes(treeNodeExes, str); } void SearchOnly(SyncTreeViewEx tree, TreeNodeEx nodeEx, str) { List<TreeNodeEx> treeNodeExes = new List<TreeNodeEx>(); treeNodeExes.Add(nodeEx); SearchNodes(treeNodeExes, str); } } |
検索範囲が指定されたらSyncTreeView.GetTreeNodeExsでTreeNodeExのリストを作成して、そのなかを調べます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
public partial class SearchForm : Form { void SearchNodes(List<TreeNodeEx> treeNodeExes, str) { progressBar1.Minimum = 0; progressBar1.Maximum = treeNodeExes.Count; List<TreeNodeEx> retTreeNodeExes = new List<TreeNodeEx>(); foreach (TreeNodeEx node in treeNodeExes) { if (IsCancel) { this.Dispose(); return; } progressBar1.Value++; Data data = (Data)node.Data; string text = data.RichData.Text; if (text == null || text == "") continue; if (text.IndexOf(textBox1.Text) != -1) { retTreeNodeExes.Add(node); } } if (retTreeNodeExes.Count == 0) { MessageBox.Show("文字列は見つかりませんでした", "検索結果"); this.Dispose(); return; } SearchResultForm form = new SearchResultForm(); form._treeNodeExes = retTreeNodeExes; form._str = str; if (!this.IsDisposed) this.Dispose(); Form1._searchResultForms.Add(form); form.Text = String.Format("「{0}」の検索結果", str); form.ShowDialog(null); } } |
検索結果を表示するフォームを表示します。そしてそれをリストに格納しています。
最後に検索結果を表示するフォームです。ListBoxは選択アイテムが変更した後のイベントしかないので、変更があったらそれをフィールド変数に保存して、それを利用して変更前後のアイテムがそれぞれどれであるかがわかるようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
public partial class SearchResultForm : Form { public SearchResultForm() { InitializeComponent(); } int _prevSelect = -1; public List<TreeNodeEx> _treeNodeExes = null; public bool _isIgnoreSelectChanged = false; public string _str = ""; private void SearchResultForm_Load(object sender, EventArgs e) { UpdateSearchResult(); } void UpdateSearchResult() { if (_treeNodeExes == null) return; listBox1.Items.Clear(); foreach (TreeNodeEx nodeEx in _treeNodeExes) { listBox1.Items.Add(nodeEx.Text); } } private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { if (_isIgnoreSelectChanged) return; if (_prevSelect != -1) { Data data = (Data)_treeNodeExes[_prevSelect].Data; data.RichData = syncRichTextBoxEx1.Data; } _prevSelect = listBox1.SelectedIndex; if (_prevSelect != -1) { Data data1 = (Data)_treeNodeExes[_prevSelect].Data; syncRichTextBoxEx1.Data = data1.RichData; } } } |