Лучший отвечающий
C#:Treeview - организовать поиск

Вопрос
-
Огромное спасибо Malobukv за вашу помощь.
Что ещё хотелось бы узнать как лучше организовать поиск по табельному и Фио сотрудника, которые будут вводиться в textbox?
После того как нашёл необходимого сотрудника по событию afterselect должна появляться новая форма, привязанная именно для этого сотрудника. Так вот вопрос каким образом мне это оптимально сделать?
- Разделено Abolmasov Dmitry 5 апреля 2012 г. 9:42
27 марта 2012 г. 21:50
Ответы
-
> организовать поиск по табельному и Фио сотрудника, которые будут вводиться в textbox?
в предыдущем примере: public Form1() {...} -- замените следующим кодом:public Form1() { this.Size = new System.Drawing.Size(600, 800); var tv = new TreeView { Parent = this, Dock = DockStyle.Fill }; var xe = XElement.Load("..\\..\\data.xml"); Fill(tv.Nodes, xe.XPathSelectElement("//Department[Parent_Dept_Code='00000000']")); tv.ExpandAll(); var nodes = Flatten(tv.Nodes); var selected = new List<TreeNode>(); new TextBox { Parent = this, Dock = DockStyle.Top } .TextChanged += (s, e) => { var tb = s as TextBox; foreach (var n in selected) n.BackColor = Color.Transparent; selected.Clear(); if (string.IsNullOrWhiteSpace(tb.Text)) return; foreach (var n in nodes.Where(tn => tn.Text.IndexOf(tb.Text, StringComparison.OrdinalIgnoreCase) > -1)) { n.BackColor = Color.AntiqueWhite; selected.Add(n); } }; } IEnumerable<TreeNode> Flatten(TreeNodeCollection tc) { foreach (TreeNode n in tc) { yield return n; foreach (var c in Flatten(n.Nodes)) yield return c; } }
если надо подсветить/выделить часть TreeNode.Text, то см. здесь
- Предложено в качестве ответа Malobukv 28 марта 2012 г. 20:17
- Изменено Malobukv 28 марта 2012 г. 20:32
- Помечено в качестве ответа Abolmasov Dmitry 5 апреля 2012 г. 9:53
28 марта 2012 г. 20:17 -
> создать наследников TreeNode. в них надо хранить дополнительную информацию. при поиске по дереву проверять тип узла и выполнять необходимы действия.
примерно так.
using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { var tv = new TreeView { Dock = DockStyle.Fill, Parent = this }; var td = new Department() { Text = "Отдел" }; var ts = new Staff() { Text = "Должность" }; var p1 = new Person() { Text = "11 22 33", FamilyName = "11" }; var p2 = new Person() { Text = "Qq Ww 33", FamilyName = "Qq" }; td.Nodes.Add(ts); ts.Nodes.Add(p1); ts.Nodes.Add(p2); tv.Nodes.Add(td); tv.ExpandAll(); var nodes = Flatten(tv.Nodes); var selected = new List<TreeNode>(); var tb = new TextBox { Dock = DockStyle.Top, Parent = this }; this.Shown += delegate { tb.Focus(); }; tb.TextChanged += (s, e) => { // убрать фон у выделенных узлов foreach (var n in selected) n.BackColor = Color.Transparent; selected.Clear(); if (string.IsNullOrWhiteSpace(tb.Text)) return; // найти и выделить узлы типа Person, в которых встречается введенный текст foreach (var n in nodes.OfType<Person>().Where(n => n.Text.IndexOf(tb.Text, StringComparison.OrdinalIgnoreCase) > -1)) { n.BackColor = Color.Silver; selected.Add(n); } // выделить узел типа Person, у которого свойство FamilyName == tb.Text var sn = selected.OfType<Person>().Where(n => n.FamilyName.Equals(tb.Text, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (sn != null) { tv.SelectedNode = sn; tv.Focus(); } }; } class Department : TreeNode { } class Staff : TreeNode { } class Person : TreeNode { public string FamilyName { get; set; } } IEnumerable<TreeNode> Flatten(TreeNodeCollection tc) { foreach (TreeNode n in tc) { yield return n; foreach (var c in Flatten(n.Nodes)) yield return c; } } } }
- Изменено Malobukv 3 апреля 2012 г. 13:44
- Предложено в качестве ответа Malobukv 4 апреля 2012 г. 17:27
- Помечено в качестве ответа Abolmasov Dmitry 5 апреля 2012 г. 9:53
3 апреля 2012 г. 13:43
Все ответы
-
> организовать поиск по табельному и Фио сотрудника, которые будут вводиться в textbox?
в предыдущем примере: public Form1() {...} -- замените следующим кодом:public Form1() { this.Size = new System.Drawing.Size(600, 800); var tv = new TreeView { Parent = this, Dock = DockStyle.Fill }; var xe = XElement.Load("..\\..\\data.xml"); Fill(tv.Nodes, xe.XPathSelectElement("//Department[Parent_Dept_Code='00000000']")); tv.ExpandAll(); var nodes = Flatten(tv.Nodes); var selected = new List<TreeNode>(); new TextBox { Parent = this, Dock = DockStyle.Top } .TextChanged += (s, e) => { var tb = s as TextBox; foreach (var n in selected) n.BackColor = Color.Transparent; selected.Clear(); if (string.IsNullOrWhiteSpace(tb.Text)) return; foreach (var n in nodes.Where(tn => tn.Text.IndexOf(tb.Text, StringComparison.OrdinalIgnoreCase) > -1)) { n.BackColor = Color.AntiqueWhite; selected.Add(n); } }; } IEnumerable<TreeNode> Flatten(TreeNodeCollection tc) { foreach (TreeNode n in tc) { yield return n; foreach (var c in Flatten(n.Nodes)) yield return c; } }
если надо подсветить/выделить часть TreeNode.Text, то см. здесь
- Предложено в качестве ответа Malobukv 28 марта 2012 г. 20:17
- Изменено Malobukv 28 марта 2012 г. 20:32
- Помечено в качестве ответа Abolmasov Dmitry 5 апреля 2012 г. 9:53
28 марта 2012 г. 20:17 -
> После того как нашёл необходимого сотрудника по событию afterselect должна появляться новая форма, привязанная именно для этого сотрудника.
в конструктор Form1 надо добавить примерно следующий код:
tv.AfterSelect += (s, e) => { var frm = new SomeForm(e.Node); frm.ShowDialog(); };
или примерно такой код:
var p = new Panel { Parent = this, Dock = DockStyle.Bottom, Height = 200 }; tv.AfterSelect += (s, e) => { p.Controls.Clear(); new Label { Parent = p, Text = e.Node.Text }; // далее поля ввода };
28 марта 2012 г. 20:29 -
СПС. Но вот что-то не определяет var nodes = Flatten(tv.Nodes); - что за flatten???
И вот тут ещё? как мне добавить данный код в buttonclick?? Возникает ошибка в связи с использованием объекта e
tv.AfterSelect += (s, e) => { var frm = new SomeForm(e.Node); frm.ShowDialog(); };
И, пожалуйста, можно хоть немного коментировать код...
30 марта 2012 г. 19:57 -
> не определяет var nodes = Flatten(tv.Nodes); - что за flatten???
выше по теме есть определение метода Flatten.
IEnumerable<TreeNode> Flatten(TreeNodeCollection tc) { foreach (TreeNode n in tc) { yield return n; foreach (var c in Flatten(n.Nodes)) yield return c; } }
31 марта 2012 г. 6:43 -
Да уж, извините, не заметил.
А как сделать помимо выделения дерево раскрылось и указатель был на в ведённом сотруднике???И как организовать поиск по табельному???
31 марта 2012 г. 17:57 -
> А как сделать помимо выделения дерево раскрылось и указатель был на в ведённом сотруднике?
в обработчик TextChanged (см. выше в примере) надо добавить примерно такой код:var sn = nodes.Where(tn => tn.Text.IndexOf(tb.Text, StringComparison.OrdinalIgnoreCase) > -1).FirstOrDefault(); if(sn != null) sn.TreeView.SelectedNode = sn;
2 апреля 2012 г. 8:28 -
> как организовать поиск по табельному?
уточните вопрос. что надо найти?
в дерево выводятся департаменты, должности, сотрудники. сейчас поиск осуществляется по всем узлам дерева.
2 апреля 2012 г. 8:33 -
Данный поиск находит буквы введённые в textbox, и ищет соответствие данных букв node.text,а нужен поиск только по фамилии.
Нужно организовать поиск по табельному сотрудника и фамилии, т.е в xml есть поле Personal_Number и LastName. Вот именно по этим полям при вводе в textbox и должен происходить поиск, а выделять в обоих случаях должно фамилию, т.е. lastName.
Нашли первого сотрудника и выделили, затем ищем 2-го и его тоже выделили, а как снять выделение с 1-го и со всех предыдущих??? Т.е. нужно чтобы каждый раз при поиске выделяло только то что мы ищем и ничего больше?
- Изменено vantur 2 апреля 2012 г. 9:34
2 апреля 2012 г. 9:11 -
> нужен поиск только по фамилии.
т.е. в узлах надо хранить информацию о типе данных. для этого добавляйте в дерево наследников TreeNode. например,class Person : TreeNode { public string FamilyName { get; set; } }
при поиске узлов проверяйте тип узла и есть ли совпадение. примерно так:Person p = node as Person; if(p != null && p.FamilyName.IndexOf(txt) > -1) { p.TreeView.SelectedNode = p; }
2 апреля 2012 г. 12:43 -
что-то не работает, всё равно тоже самое получается...
А как насчёт других вопросов???2 апреля 2012 г. 22:11 -
> что-то не работает, всё равно тоже самое получается...
покажите код
> организовать поиск по табельному сотрудника и фамилии, т.е в xml есть поле Personal_Number и LastName
как уже говорил, надо создать наследников TreeNode. в них надо хранить дополнительную информацию. при поиске по дереву проверять тип узла и выполнять необходимы действия.
> Нашли первого сотрудника и выделили, затем ищем 2-го и его тоже выделили, а как снять выделение с 1-го и со всех предыдущих???
выше в примере см. var selected = new List<TreeNode>();
предназначен для снятия выделение при каждом новом поиске.
3 апреля 2012 г. 8:00 -
private void button1_Click(object sender, EventArgs e) { var nodes = Flatten(treeView3.Nodes); var selected = new List<TreeNode>(); foreach (var n in selected) n.BackColor = Color.Transparent; selected.Clear(); if (string.IsNullOrWhiteSpace(textBox1.Text)) return; var sn = nodes.Where(tn => tn.Text.IndexOf(textBox1.Text, StringComparison.OrdinalIgnoreCase) > -1).FirstOrDefault(); if (sn != null) sn.TreeView.SelectedNode = sn; foreach (var n in nodes.Where(tn => tn.Text.IndexOf(textBox1.Text, StringComparison.OrdinalIgnoreCase) > -1)) { n.BackColor = Color.LightBlue; selected.Add(n); } } IEnumerable<TreeNode> Flatten(TreeNodeCollection tc) { foreach (TreeNode n in tc) { yield return n; foreach (var c in Flatten(n.Nodes)) yield return c; } }
var selected = new List<TreeNode>(); - предназначен, но почему не очищает??? Где повторно нужно его вызвать в коде?
Вы говорили: надо создать наследников TreeNode. в них надо хранить дополнительную информацию. при поиске по дереву проверять тип узла и выполнять необходимы действия.
Реализуйте, пожалуйста, данное в приведенном коде, а то что-то я вообще не пойму как это сделать...
3 апреля 2012 г. 9:16 -
> var selected = new List<TreeNode>(); - предназначен, но почему не очищает?
selected должен быть определен за пределами обработчика button1_Click, примерно так:List<TreeNode> selected = new List<TreeNode>(); private void button1_Click(object sender, EventArgs e) { }
3 апреля 2012 г. 10:36 -
> создать наследников TreeNode. в них надо хранить дополнительную информацию. при поиске по дереву проверять тип узла и выполнять необходимы действия.
примерно так.
using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { var tv = new TreeView { Dock = DockStyle.Fill, Parent = this }; var td = new Department() { Text = "Отдел" }; var ts = new Staff() { Text = "Должность" }; var p1 = new Person() { Text = "11 22 33", FamilyName = "11" }; var p2 = new Person() { Text = "Qq Ww 33", FamilyName = "Qq" }; td.Nodes.Add(ts); ts.Nodes.Add(p1); ts.Nodes.Add(p2); tv.Nodes.Add(td); tv.ExpandAll(); var nodes = Flatten(tv.Nodes); var selected = new List<TreeNode>(); var tb = new TextBox { Dock = DockStyle.Top, Parent = this }; this.Shown += delegate { tb.Focus(); }; tb.TextChanged += (s, e) => { // убрать фон у выделенных узлов foreach (var n in selected) n.BackColor = Color.Transparent; selected.Clear(); if (string.IsNullOrWhiteSpace(tb.Text)) return; // найти и выделить узлы типа Person, в которых встречается введенный текст foreach (var n in nodes.OfType<Person>().Where(n => n.Text.IndexOf(tb.Text, StringComparison.OrdinalIgnoreCase) > -1)) { n.BackColor = Color.Silver; selected.Add(n); } // выделить узел типа Person, у которого свойство FamilyName == tb.Text var sn = selected.OfType<Person>().Where(n => n.FamilyName.Equals(tb.Text, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (sn != null) { tv.SelectedNode = sn; tv.Focus(); } }; } class Department : TreeNode { } class Staff : TreeNode { } class Person : TreeNode { public string FamilyName { get; set; } } IEnumerable<TreeNode> Flatten(TreeNodeCollection tc) { foreach (TreeNode n in tc) { yield return n; foreach (var c in Flatten(n.Nodes)) yield return c; } } } }
- Изменено Malobukv 3 апреля 2012 г. 13:44
- Предложено в качестве ответа Malobukv 4 апреля 2012 г. 17:27
- Помечено в качестве ответа Abolmasov Dmitry 5 апреля 2012 г. 9:53
3 апреля 2012 г. 13:43 -
А как мне задать FamilyName именно для всех сотрудников, прописывать вручную для всех?
Что-то не совсем понятно... Можно данный код изменить именно для моего treeview и моего xml и привести текст? СПС...
3 апреля 2012 г. 17:03 -
> А как мне задать FamilyName именно для всех сотрудников, прописывать вручную для всех?
дерево заполняется в методе Fill (см. выше);
в нем есть строка tn.Nodes.Add(p.LastName + " " + p.FirstName);
ее надо заменить на следующую:tn.Nodes.Add(new Person { Text = p.LastName + " " + p.FirstName, FamilyName = p.LastName });
3 апреля 2012 г. 20:24