From 472cd6d16ffa137277321ddec8caa82d92af1160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=9F=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=BF=D0=BE=D0=B2?= Date: Mon, 23 Sep 2024 14:37:08 +0400 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B2=D0=B5=D1=80=D1=88=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=80=D0=B0=D0=B7=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D1=83=20treeview?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Exceptions/NodeIsNotLeafException.cs | 7 + .../Exceptions/NotSelectedNodeException.cs | 7 + .../PropertyNotDeclaratedException.cs | 7 + .../Exceptions/PropertyNullException.cs | 7 + .../TreeHierarchyNotSetException.cs | 7 + .../UserControlTreeViewException.cs | 8 + .../UserControlTreeView.Designer.cs | 56 +++++++ .../Components/UserControlTreeView.cs | 142 ++++++++++++++++++ .../Components/UserControlTreeView.resx | 120 +++++++++++++++ WinFormSolution/WinFormsApp/Employee.cs | 22 +++ WinFormSolution/WinFormsApp/Form.Designer.cs | 134 ++++++++++++++++- WinFormSolution/WinFormsApp/Form.cs | 62 ++++++++ 12 files changed, 577 insertions(+), 2 deletions(-) create mode 100644 WinFormSolution/Components/Exceptions/NodeIsNotLeafException.cs create mode 100644 WinFormSolution/Components/Exceptions/NotSelectedNodeException.cs create mode 100644 WinFormSolution/Components/Exceptions/PropertyNotDeclaratedException.cs create mode 100644 WinFormSolution/Components/Exceptions/PropertyNullException.cs create mode 100644 WinFormSolution/Components/Exceptions/TreeHierarchyNotSetException.cs create mode 100644 WinFormSolution/Components/Exceptions/UserControlTreeViewException.cs create mode 100644 WinFormSolution/Components/UserControlTreeView.Designer.cs create mode 100644 WinFormSolution/Components/UserControlTreeView.cs create mode 100644 WinFormSolution/Components/UserControlTreeView.resx create mode 100644 WinFormSolution/WinFormsApp/Employee.cs diff --git a/WinFormSolution/Components/Exceptions/NodeIsNotLeafException.cs b/WinFormSolution/Components/Exceptions/NodeIsNotLeafException.cs new file mode 100644 index 0000000..27f3e51 --- /dev/null +++ b/WinFormSolution/Components/Exceptions/NodeIsNotLeafException.cs @@ -0,0 +1,7 @@ +namespace Components.Exceptions +{ + public class NodeIsNotLeafException : UserControlTreeViewException + { + public NodeIsNotLeafException() : base("Selected node is not a leaf") { } + } +} diff --git a/WinFormSolution/Components/Exceptions/NotSelectedNodeException.cs b/WinFormSolution/Components/Exceptions/NotSelectedNodeException.cs new file mode 100644 index 0000000..f9e57db --- /dev/null +++ b/WinFormSolution/Components/Exceptions/NotSelectedNodeException.cs @@ -0,0 +1,7 @@ +namespace Components.Exceptions +{ + public class NotSelectedNodeException : UserControlTreeViewException + { + public NotSelectedNodeException() : base("Node is not selected") { } + } +} diff --git a/WinFormSolution/Components/Exceptions/PropertyNotDeclaratedException.cs b/WinFormSolution/Components/Exceptions/PropertyNotDeclaratedException.cs new file mode 100644 index 0000000..cb04f15 --- /dev/null +++ b/WinFormSolution/Components/Exceptions/PropertyNotDeclaratedException.cs @@ -0,0 +1,7 @@ +namespace Components.Exceptions +{ + public class PropertyNotDeclaratedException : UserControlTreeViewException + { + public PropertyNotDeclaratedException(string propName) : base($"Property \"{propName}\" not declared") { } + } +} diff --git a/WinFormSolution/Components/Exceptions/PropertyNullException.cs b/WinFormSolution/Components/Exceptions/PropertyNullException.cs new file mode 100644 index 0000000..4b664fb --- /dev/null +++ b/WinFormSolution/Components/Exceptions/PropertyNullException.cs @@ -0,0 +1,7 @@ +namespace Components.Exceptions +{ + public class PropertyNullException : UserControlTreeViewException + { + public PropertyNullException(string propName) : base($"Property \"{propName}\" is null") { } + } +} diff --git a/WinFormSolution/Components/Exceptions/TreeHierarchyNotSetException.cs b/WinFormSolution/Components/Exceptions/TreeHierarchyNotSetException.cs new file mode 100644 index 0000000..705d2a6 --- /dev/null +++ b/WinFormSolution/Components/Exceptions/TreeHierarchyNotSetException.cs @@ -0,0 +1,7 @@ +namespace Components.Exceptions +{ + public class TreeHierarchyNotSetException : UserControlTreeViewException + { + public TreeHierarchyNotSetException() : base("Tree hierarchy not set") { } + } +} diff --git a/WinFormSolution/Components/Exceptions/UserControlTreeViewException.cs b/WinFormSolution/Components/Exceptions/UserControlTreeViewException.cs new file mode 100644 index 0000000..7c46527 --- /dev/null +++ b/WinFormSolution/Components/Exceptions/UserControlTreeViewException.cs @@ -0,0 +1,8 @@ +namespace Components.Exceptions +{ + public class UserControlTreeViewException : Exception + { + public UserControlTreeViewException() { } + public UserControlTreeViewException(string message) : base(message) { } + } +} diff --git a/WinFormSolution/Components/UserControlTreeView.Designer.cs b/WinFormSolution/Components/UserControlTreeView.Designer.cs new file mode 100644 index 0000000..9c49b0b --- /dev/null +++ b/WinFormSolution/Components/UserControlTreeView.Designer.cs @@ -0,0 +1,56 @@ +namespace Components +{ + partial class UserControlTreeView + { + /// + /// Обязательная переменная конструктора. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Освободить все используемые ресурсы. + /// + /// истинно, если управляемый ресурс должен быть удален; иначе ложно. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Код, автоматически созданный конструктором компонентов + + /// + /// Требуемый метод для поддержки конструктора — не изменяйте + /// содержимое этого метода с помощью редактора кода. + /// + private void InitializeComponent() + { + treeView = new TreeView(); + SuspendLayout(); + // + // treeView + // + treeView.Location = new Point(22, 17); + treeView.Name = "treeView"; + treeView.Size = new Size(188, 285); + treeView.TabIndex = 0; + // + // UserControlTreeView + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + BackColor = SystemColors.ActiveCaption; + Controls.Add(treeView); + Name = "UserControlTreeView"; + Size = new Size(232, 335); + ResumeLayout(false); + } + + #endregion + + private TreeView treeView; + } +} diff --git a/WinFormSolution/Components/UserControlTreeView.cs b/WinFormSolution/Components/UserControlTreeView.cs new file mode 100644 index 0000000..52a3623 --- /dev/null +++ b/WinFormSolution/Components/UserControlTreeView.cs @@ -0,0 +1,142 @@ +using Components.Exceptions; +using System.Reflection; + +namespace Components +{ + public partial class UserControlTreeView : UserControl + { + public int SelectedIndex + { + get + { + return treeView.SelectedNode?.Index ?? -1; + } + set + { + if (value > -1 && value < treeView.Nodes.Count) + { + treeView.SelectedNode = treeView.Nodes[value]; + } + } + } + private List<(string PropertyName, bool AlwaysCreateBranch)> Hierarchy; + public UserControlTreeView() + { + InitializeComponent(); + Hierarchy = []; + } + public T GetObjectSelectedNode() + where T : class, new() + { + var node = treeView.SelectedNode; + + if (node == null) + { + throw new NotSelectedNodeException(); + } + + if ((Hierarchy?.Count ?? 0) > 0) + { + throw new TreeHierarchyNotSetException(); + } + + if (node.Nodes.Count > 0) + { + throw new NodeIsNotLeafException(); + } + + T obj = new T(); + int propIndex = GetNodeDepth(node); + while (node != null) + { + string propValue = node.Text; + string propName = Hierarchy[propIndex].PropertyName; + + var prop = obj.GetType().GetProperty(propName); + if (prop == null) + { + throw new PropertyNotDeclaratedException(propName); + } + + prop.SetValue(obj, propValue); + + node = node.Parent; + propIndex--; + } + + return obj; + } + private int GetNodeDepth(TreeNode node) + { + int depth = 0; + while (node.Parent != null) + { + depth++; + node = node.Parent; + } + return depth; + } + public void SetTreeObjects(List objects) + { + if (objects.Count == 0) + { + return; + } + + if ((Hierarchy?.Count ?? 0) > 0) + { + throw new TreeHierarchyNotSetException(); + } + + PropertyInfo[]? properties = objects[0]!.GetType().GetProperties(); + ClearTreeView(); + foreach (T obj in objects) + { + var nodes = treeView.Nodes; + foreach (var hierarchyProperty in Hierarchy) + { + PropertyInfo? objectPropertyInfo = properties?.Single(prop => prop.Name == hierarchyProperty.PropertyName); + if (objectPropertyInfo == null) + { + throw new PropertyNotDeclaratedException(hierarchyProperty.PropertyName); + } + string? objectPropertyValue = objectPropertyInfo.GetValue(obj)?.ToString() ?? null; + if (objectPropertyValue == null) + { + throw new PropertyNullException(hierarchyProperty.PropertyName); + } + + TreeNode? node = null; + + if (!hierarchyProperty.AlwaysCreateBranch) + { + foreach (TreeNode childNode in nodes) + { + if (childNode.Text == objectPropertyValue) + { + node = childNode; + break; + } + } + } + + if (node == null) + { + node = nodes.Add(objectPropertyValue); + } + + nodes = node.Nodes; + } + } + } + public void SetHierarchy(List<(string PropertyName, bool AlwaysCreateBranch)> hierarchy) + { + Hierarchy = hierarchy; + } + public void ClearTreeView() + { + treeView.Nodes.Clear(); + treeView.Update(); + } + } +} diff --git a/WinFormSolution/Components/UserControlTreeView.resx b/WinFormSolution/Components/UserControlTreeView.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/WinFormSolution/Components/UserControlTreeView.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/WinFormSolution/WinFormsApp/Employee.cs b/WinFormSolution/WinFormsApp/Employee.cs new file mode 100644 index 0000000..b6c215f --- /dev/null +++ b/WinFormSolution/WinFormsApp/Employee.cs @@ -0,0 +1,22 @@ +namespace WinFormsApp +{ + public class Employee + { + public string Departament { get; set; } + public string Position { get; set; } + public string Name { get; set; } + public string Surname { get; set; } + public Employee() { } + public Employee(string departament, string position, string surname, string name) + { + Departament = departament; + Position = position; + Name = name; + Surname = surname; + } + public override string ToString() + { + return Departament + ", " + Position + ", " + Surname + " " + Name; + } + } +} diff --git a/WinFormSolution/WinFormsApp/Form.Designer.cs b/WinFormSolution/WinFormsApp/Form.Designer.cs index e772409..f55dc8c 100644 --- a/WinFormSolution/WinFormsApp/Form.Designer.cs +++ b/WinFormSolution/WinFormsApp/Form.Designer.cs @@ -31,6 +31,17 @@ userControlCheckedList = new Components.UserControlCheckedList(); buttonFillCheckedList = new Button(); buttonClearList = new Button(); + userControlDatePicker = new Components.UserControlDatePicker(); + dateTimePickerMinDate = new DateTimePicker(); + dateTimePicker1 = new DateTimePicker(); + label1 = new Label(); + label2 = new Label(); + userControlTreeView = new Components.UserControlTreeView(); + buttonFillTreeView = new Button(); + buttonClearTreeView = new Button(); + buttonShowTreeViewNode = new Button(); + textBoxTreeViewSelectedNodeIndex = new TextBox(); + textBoxTreeViewSelectedObject = new TextBox(); SuspendLayout(); // // userControlCheckedList @@ -38,7 +49,7 @@ userControlCheckedList.BackColor = Color.Firebrick; userControlCheckedList.Location = new Point(12, 12); userControlCheckedList.Name = "userControlCheckedList"; - userControlCheckedList.Size = new Size(315, 170); + userControlCheckedList.Size = new Size(168, 170); userControlCheckedList.TabIndex = 0; // // buttonFillCheckedList @@ -61,17 +72,125 @@ buttonClearList.UseVisualStyleBackColor = true; buttonClearList.Click += buttonClearList_Click; // + // userControlDatePicker + // + userControlDatePicker.BackColor = Color.Orange; + userControlDatePicker.Location = new Point(273, 12); + userControlDatePicker.Name = "userControlDatePicker"; + userControlDatePicker.Size = new Size(121, 50); + userControlDatePicker.TabIndex = 3; + // + // dateTimePickerMinDate + // + dateTimePickerMinDate.Format = DateTimePickerFormat.Short; + dateTimePickerMinDate.Location = new Point(246, 95); + dateTimePickerMinDate.Name = "dateTimePickerMinDate"; + dateTimePickerMinDate.Size = new Size(91, 23); + dateTimePickerMinDate.TabIndex = 4; + // + // dateTimePicker1 + // + dateTimePicker1.Format = DateTimePickerFormat.Short; + dateTimePicker1.Location = new Point(343, 95); + dateTimePicker1.Name = "dateTimePicker1"; + dateTimePicker1.Size = new Size(95, 23); + dateTimePicker1.TabIndex = 5; + // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(264, 77); + label1.Name = "label1"; + label1.Size = new Size(52, 15); + label1.TabIndex = 6; + label1.Text = "MinDate"; + // + // label2 + // + label2.AutoSize = true; + label2.Location = new Point(361, 77); + label2.Name = "label2"; + label2.Size = new Size(54, 15); + label2.TabIndex = 7; + label2.Text = "MaxDate"; + // + // userControlTreeView + // + userControlTreeView.BackColor = SystemColors.ActiveCaption; + userControlTreeView.Location = new Point(498, 12); + userControlTreeView.Name = "userControlTreeView"; + userControlTreeView.SelectedIndex = 0; + userControlTreeView.Size = new Size(232, 320); + userControlTreeView.TabIndex = 8; + // + // buttonFillTreeView + // + buttonFillTreeView.Location = new Point(498, 348); + buttonFillTreeView.Name = "buttonFillTreeView"; + buttonFillTreeView.Size = new Size(75, 23); + buttonFillTreeView.TabIndex = 9; + buttonFillTreeView.Text = "Заполнить"; + buttonFillTreeView.UseVisualStyleBackColor = true; + buttonFillTreeView.Click += buttonFillTreeView_Click; + // + // buttonClearTreeView + // + buttonClearTreeView.Location = new Point(574, 348); + buttonClearTreeView.Name = "buttonClearTreeView"; + buttonClearTreeView.Size = new Size(75, 23); + buttonClearTreeView.TabIndex = 10; + buttonClearTreeView.Text = "Очистить"; + buttonClearTreeView.UseVisualStyleBackColor = true; + buttonClearTreeView.Click += buttonClearTreeView_Click; + // + // buttonShowTreeViewNode + // + buttonShowTreeViewNode.Location = new Point(655, 348); + buttonShowTreeViewNode.Name = "buttonShowTreeViewNode"; + buttonShowTreeViewNode.Size = new Size(75, 23); + buttonShowTreeViewNode.TabIndex = 11; + buttonShowTreeViewNode.Text = "Показать"; + buttonShowTreeViewNode.UseVisualStyleBackColor = true; + buttonShowTreeViewNode.Click += buttonShowTreeViewNode_Click; + // + // textBoxTreeViewSelectedNodeIndex + // + textBoxTreeViewSelectedNodeIndex.Location = new Point(630, 397); + textBoxTreeViewSelectedNodeIndex.Name = "textBoxTreeViewSelectedNodeIndex"; + textBoxTreeViewSelectedNodeIndex.Size = new Size(100, 23); + textBoxTreeViewSelectedNodeIndex.TabIndex = 12; + // + // textBoxTreeViewSelectedObject + // + textBoxTreeViewSelectedObject.Location = new Point(31, 397); + textBoxTreeViewSelectedObject.Name = "textBoxTreeViewSelectedObject"; + textBoxTreeViewSelectedObject.ReadOnly = true; + textBoxTreeViewSelectedObject.Size = new Size(593, 23); + textBoxTreeViewSelectedObject.TabIndex = 13; + // // Form // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(697, 459); + ClientSize = new Size(768, 470); + Controls.Add(textBoxTreeViewSelectedObject); + Controls.Add(textBoxTreeViewSelectedNodeIndex); + Controls.Add(buttonShowTreeViewNode); + Controls.Add(buttonClearTreeView); + Controls.Add(buttonFillTreeView); + Controls.Add(userControlTreeView); + Controls.Add(label2); + Controls.Add(label1); + Controls.Add(dateTimePicker1); + Controls.Add(dateTimePickerMinDate); + Controls.Add(userControlDatePicker); Controls.Add(buttonClearList); Controls.Add(buttonFillCheckedList); Controls.Add(userControlCheckedList); Name = "Form"; Text = "Form"; ResumeLayout(false); + PerformLayout(); } #endregion @@ -79,5 +198,16 @@ private Components.UserControlCheckedList userControlCheckedList; private Button buttonFillCheckedList; private Button buttonClearList; + private Components.UserControlDatePicker userControlDatePicker; + private DateTimePicker dateTimePickerMinDate; + private DateTimePicker dateTimePicker1; + private Label label1; + private Label label2; + private Components.UserControlTreeView userControlTreeView; + private Button buttonFillTreeView; + private Button buttonClearTreeView; + private Button buttonShowTreeViewNode; + private TextBox textBoxTreeViewSelectedNodeIndex; + private TextBox textBoxTreeViewSelectedObject; } } diff --git a/WinFormSolution/WinFormsApp/Form.cs b/WinFormSolution/WinFormsApp/Form.cs index 9fa6729..0cfa343 100644 --- a/WinFormSolution/WinFormsApp/Form.cs +++ b/WinFormSolution/WinFormsApp/Form.cs @@ -1,3 +1,5 @@ +using Components.Exceptions; + namespace WinFormsApp { public partial class Form : System.Windows.Forms.Form @@ -24,5 +26,65 @@ namespace WinFormsApp { userControlCheckedList.ClearCheckedListBoxValues(); } + + private void buttonFillTreeView_Click(object sender, EventArgs e) + { + List employees = new List(); + employees.Add(new Employee(" ", "", "", "")); + employees.Add(new Employee(" ", "", "", "")); + employees.Add(new Employee(" ", "", "", "")); + employees.Add(new Employee(" ", "", "", "")); + + employees.Add(new Employee(" ", "", "", "")); + employees.Add(new Employee(" ", "", "", "")); + employees.Add(new Employee(" ", "", "", "")); + employees.Add(new Employee(" ", " ", "", "")); + + employees.Add(new Employee(" ", " ", "", "")); + employees.Add(new Employee(" ", "PR-", "", "")); + employees.Add(new Employee(" ", "", "", "")); + employees.Add(new Employee(" ", "", "", "")); + + List<(string PropertyName, bool AlwaysCreateBranch)> hierarchy = new(); + + hierarchy.Add(("Departament", false)); + hierarchy.Add(("Position", false)); + hierarchy.Add(("Surname", false)); + hierarchy.Add(("Name", false)); + + userControlTreeView.SetHierarchy(hierarchy); + + userControlTreeView.SetTreeObjects(employees); + } + + private void buttonClearTreeView_Click(object sender, EventArgs e) + { + userControlTreeView.ClearTreeView(); + } + + private void buttonShowTreeViewNode_Click(object sender, EventArgs e) + { + Employee employee; + try + { + employee = userControlTreeView.GetObjectSelectedNode(); + textBoxTreeViewSelectedObject.Text = employee.ToString(); + } + catch (PropertyNotDeclaratedException ex) + { + MessageBox.Show(ex.Message); + textBoxTreeViewSelectedObject.Text = string.Empty; + } + catch (PropertyNullException ex) + { + MessageBox.Show(ex.Message); + textBoxTreeViewSelectedObject.Text = string.Empty; + } + catch (NotSelectedNodeException ex) + { + MessageBox.Show(ex.Message); + textBoxTreeViewSelectedObject.Text = string.Empty; + } + } } }