Using system;
Using system.collections;
Using system.componentmodel;
Using system.drawing;
Using system.data;
Using system.windows.forms;
Using system.diagnostics;
Namespace UpControls
{
///
/// The tree that can be quickly bound to the relational table or a single table, the tree automatically binds according to the primarykey column value of the primary table and its subtables.
/// only travers all the rows in ROWS, so the loading speed is very fast.
/// Node content can only display the value, or the column name can be displayed
/// Relational data source requirements have: Subliers must have unique constraints
/// Additional column must be the column owned by the bottom table in the relational table
/// Suitable for tree fills outside of ParentID, ID, TEXT
/// summary>
Public Class DataReview: TreeView
{
Private system.componentmodel.Container Components = NULL;
Private DataTable_MainDataTable;
Private string [] _APpendColumnnames = NULL;
Private system.windows.Forms.ContextMenu CNTMENU;
Private bool _columnnameontext;
PRIVATE TREENODE _PARENTNODE;
Public datatreeView ()
{
InitializationComponent ();
Menuitem MnU;
Mnu = cntmenu.MenuItems.Add ("Show column name");
MNU.Click = New EventHandler (MNU_Click);
Mnu = cntmenu.MenuItems.Add ("-");
Mnu = cntmenu.MenuItems.Add ("Expand");
MNU.Click = New EventHandler (MNU_Click);
Mnu = cntmenu.MenuItems.Add ("folding");
MNU.Click = New EventHandler (MNU_Click);
Mnu = cntmenu.MenuItems.Add ("-");
Mnu = cntmenu.MenuItems.Add ("All Expand");
MNU.Click = New EventHandler (MNU_Click);
Mnu = cntmenu.MenuItems.Add ("All Folding");
MNU.Click = New EventHandler (MNU_Click);
}
///
/// Clean all the resources being used.
/// summary>
Protected Override Void Dispose (Bool Disposing)
{
IF (Disposing)
{
IF (Components! = NULL)
{
Components.dispose ();
}
}
Base.dispose (Disposing);
}
#REGION component designer generated code
///
/// Designer supports the required method - do not use the code editor
// / Modify the content of this method.
/// summary>
Private vidinitiRizeComponent () {
This.cntmenu = new system.windows.forms.contextmenu ();
This.cntMenu.popup = new system.eventhandler (this.cntMenu_popup);
THIS.CHECKBOXES = TRUE;
THIS.CONTEXTMENU = this.cntmenu;
}
#ndregion
///
///
/// The first primaryKey value of the primary table will be added to the top of the tree.
/// summary>
Public DataTable maintable
{
Get {return this._maindataable;}
}
///
In addition to the column outside the primarykey column, you can attach the column below the last primarykey column.
/// summary>
Public String [] appendcolumnnames
{
Get {return_appendcolumnnames;
}
///
/// The text of the node should be included in the column name
/// summary>
Public Bool ColumnNameOntext
{
Get {return_columnnameontext;
}
///
/// Fill a table and its sub-table to the tree, the data displayed by the node is the content of each key column.
/// summary>
/// Table to populate the tree param>
/// Which existing node is to populate param>
/// Additional column (non-key), format: Table name. Column name, or only list param>
/// Column name Do not display in the text of the node param>
/// Do you want to clear the existing node and then fill param>
Public void Fill (DataTable DataTable, Treenode Parentnode,
String [] appendcolumnnames, bool columnnameontext, bool clearnodes)
{
_MAINDATATABLE = DATATABLE;
_appendcolumnnames = appendcolumnnames;
_ColumnNameOntext = columnnameontext;
_ParentNode = ParentNode;
Trybinding (ClearNodes);
}
///
/// Try to fill the tree, if each required attribute is set up
/// summary>
/// param>
Public void trybinding (Bool ClearNodes)
{
IF (ClearNodes)
{
THIS.NODES.CLEAR ();
Trybinding (_MAINDATABLE, NULL, _APPENDCOLUMNNAMES);
Else
Trybinding (_MAINDATABLE, _PARENTNODE, _APPENDCOLUMNNAMES);
}
Private Void Trybinding (DataTable DataTable, Treenode Parentnode,
String [] appendcolumnnames)
{
IF (DATATABLE == null) return;
// Add a primary table node
IF (ParentNode! = NULL)
ParentNode = ParentNode.Nodes.Add (DataTable.tables);
Else
ParentNode = this.nodes.add (datatable.tablename);
/ / Returns an array containing all key columns in a table, but if the table is a sub-table, the key column as the relationship is not included // because there is the same column value in the parent table, no need to load repeated content Node
Datacolumn [] primarykey = addtheseprimarykey (dataable);
Treenode [] Prinodes = new Treenode [PrimaryKey.Length];
String sort = string.empty;
// Sort preparation
For (int i = 0; i Sort = Sort "," PrimaryKey [i] .columnname; // In the following data line traversal, it is necessary to ensure that it is arranged in order, quickly loading it. Sort = sort.trim (','); // The deleted line is of course not added to the tree. DataRow [] allrows = datatable.select (string.empty, sort, dataviewrowstate.currentrows); Foreach (DataRow Dr in Allrows) { // The following for setting the Prinodes array, ensuring that n node in the Prinodes corresponds to each key column of the current row. For (int i = 0; i { String colname = primarykey [i] .columnname; / / The content is null, and the contents of this key column will not be added to the tree in this line. IF (DR [ColName] == NULL) BREAK; Treenode nod = new treenode (); / / Format the text of the node This.FormatNodeText (NOD, DR, PRIMARYKEY [I]); IF (Prinodes [i]! = null) { / / If there is already existing, the key column of the front is generally allowed to repeat the content. IF (Prinodes [i] .text! = nod.text) PRINODES [I] = NOD; } Else PRINODES [I] = NOD; } INT R = 0; Treenode PNOD = NULL; / / Judge whether Node in Prinodes is to be added to the tree and where to add (not using foreach, the order is different) For (int i = 0; i { IF (Prinodes [I] == NULL) BREAK; Treenode nod = prinodes [i]; IF (r == 0) { IF (! parentnode.nodes.contains) ParentNode.Nodes.Add (NOD); } Else if (! pNOD.NODES .CONTAINS (NOD)) Pnod.nodes .add (nod); PNOD = NOD; r; } // Not set in the loop above, indicating that each key column is null, although it is not possible IF (PNOD == NULL) Continue; // Additional column must be the bottom table in the relational table IF (DataTable.Childrelations.count == 0 && AppendColumnNames! = null) { FOREACH (String Fullcolname in appendcolumnnames) { The column name in // appendcolumnnames can be: a table name. Column name, or only column name // Because a table may have multiple relationships, and the name is navigation String [] fullname = fullcolname.split ('.'); String tabname = string.empty, colname = string.empty; IF (Fullname.length> 1) { TabName = fullname [0]; ColName = fullname [1]; } Else { TabName = DataTable.tablename; Colname = fullname [0]; } IF (TabName == DataTable.tablename && DataTable.columns .contains (colname)) { Treenode nod = new treenode (); This.FormatNodeText (NOD, DR, DATATABLE.COLUMNS [ColName]); pnod.nodes.add (nod); } } } / / / The content of the sub-table is filld to the tree, and each table has only rows all over ROWS. Foreach (Dataralation DRL IN DATATABLE.CHILDRELATIONS) Trybinding (DRL.CHildTable, PNOD, AppendColumnNames); } } /// /// Returns an array containing all key columns in a table, but if the table is a sub-table, the key column as a relationship is not included (because the same column value is present in the parent table, no need to load repeated content Node) /// summary> /// param> /// Private Datacolumn [] AddTheSeprimaryKey (DataTable DT) { Datacolumn [] keys = NULL; ArrayList List = New ArrayList (); Foreach (Datacolumn DC in Dt.primaryKey) List.Add (DC); IF (dt! = this.mainTable) Foreach (DataRelation DRL IN DT.PARETRELATIONS) Foreach (Datacolumn DC in DRL.ChildColumn) List.Remove (DC); IF (List.count> 0) { Keys = new datacolumn [list.count]; List.copyto (keys, 0); } Return Keys; } /// /// Storm the node text /// summary> /// param> /// param> /// param> Private Void FormatNodeText (Treenode Node, DataRow DataRow, Datacolumn DC) { String nodetext = string.empty, namecol = string.empty, caption = string.empty; /// column_autoid uca = NULL; /// column_autoid contains information about the encoding rule of the ID column, /// if (Dc.ExtendedProperties.Containskey ("ext_autoid")) ///uca=dc.extendedProperties["ext_autoid "] as column_autoid; IF (DataRow.Table.columns.Contains (DC.Columnname)) { NodeText = DATAROW [DC] .tostring () .trim (); ///Column_autoid.idnameColumn: Save an ID column name column name, if there is this, the node text can use the name to explain the ID, such as the name of the name of the person. /// if (uca! = null && uca.idnamecolumn! = null) /// { ///namecol=uca.idnamecolumn; /// if (DataRow.Table.Columns .Contains (Namecol)) /// Namecol = DATAROW [NAMECOL] .tostring (); // Name list ///} Caption = dc.caption; IF (dc.datatype == typeof (boolean)) { NodeText = CAPTION; Node.checked = system.convert.toboolean (DATAROW [DC]); } Else { Namecol = Namecol == String.empty? Namecol: "/ t [" namecol "]" IF (this.columnnameontext) NodeText = CAPTION ":" NodeText Namecol; Else NodeText = NODETEXT NAMECOL; } Node.Text = NodeText; } } Private void CNTMENU_POPUP (Object Sender, System.Eventargs E) { } Private Void Mnu_Click (Object Sender, Eventargs E) { Menuitem Mnu = sender as menuitem; Switch (mnu.index) { Case 0: Mnu.checked =! mnu.checked; _ColumnNameOntext = mnu.checked; THIS.TRYBINDING (TRUE); Break; Case 2: IF (this.selectedNode! = null) this.selectedNode.expandall (); Break; Case 3: IF (this.selectedNode! = null) THIS.SelectedNode.collapse (); Break; Case 5: THIS.EXPANDALL (); Break; Case 6: this.collapseall (); Break; } } } }