重写DataGridView with TreeView

来源:互联网 发布:mac系统怎么编辑pdf 编辑:程序博客网 时间:2024/04/30 10:17

 TreeGridView.cs

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;

namespace DataGridTreeView
{
    
/// <summary>
    
/// Summary description for DataGridTreeView
    
/// </summary>

    [System.ComponentModel.DesignerCategory("code"),
    Designer(
typeof(System.Windows.Forms.Design.ControlDesigner)),
    ComplexBindingProperties(),
    Docking(DockingBehavior.Ask)]
    
public class TreeGridView : DataGridView
    
{
        
private int _indentWidth;
        
private TreeGridNode _root;
        
private TreeGridColumn _expandableColumn;
        
private bool _disposing = false;
        
private ImageList _imageList;
        
private bool _inExpandCollapse = false;
        
internal bool _inExpandCollapseMouseCapture = false;
        
private Control hideScrollBarControl;
        
private bool _showLines = true;
        
private bool _virtualNodes = false;

        
internal VisualStyleRenderer rOpen = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Opened);
        
internal VisualStyleRenderer rClose = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Closed);

        
public TreeGridView()
        
{
            
this.EditMode = DataGridViewEditMode.EditProgrammatically;
            
this.RowTemplate = new TreeGridNode() as DataGridViewRow;
            
this.AllowUserToAddRows = false;
            
this.AllowUserToDeleteRows = false;
            
this._root = new TreeGridNode(this);
            
this._root.IsRoot = true;

            
this.Rows.CollectionChanged += delegate(object sender, System.ComponentModel.CollectionChangeEventArgs e) { };
        }


        
protected override void OnKeyDown(KeyEventArgs e)
        
{
            
base.OnKeyDown(e);
            
if (!e.Handled)
            
{
                
if (e.KeyCode == Keys.F2 && this.CurrentCellAddress.X > -1 && this.CurrentCellAddress.Y > -1)
                
{
                    
if (!this.CurrentCell.Displayed)
                    
{
                        
this.FirstDisplayedScrollingRowIndex = this.CurrentCellAddress.Y;
                    }

                    
else
                    
{
                        
//TODO
                    }

                    
this.SelectionMode = DataGridViewSelectionMode.CellSelect;
                    
this.BeginEdit(true);
                }

                
else if (e.KeyCode == Keys.Enter && !this.IsCurrentCellInEditMode)
                
{
                    
this.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
                    
this.CurrentCell.OwningRow.Selected = true;
                }

            }

        }


        [Browsable(
false),
       DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never)]
        
public new object DataSource
        
{
            
get return null; }
            
set
            
{
                
throw new NotSupportedException("The TreeGridView doesn't support databinding!");
            }

        }


        [Browsable(
false),
       DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never)]
        
public new object DataMember
        
{
            
get return null; }
            
set throw new NotSupportedException("The TreeGridView does not support databinding"); }
        }


        [Browsable(
false),
       DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never)]
        
public new DataGridViewRowCollection Rows
        
{
            
get return base.Rows; }
        }


        [Browsable(
false),
       DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never)]
        
public new bool VirtualMode
        
{
            
get return false; }
            
set throw new NotSupportedException("The TreeGridView does not support virtual mode"); }
        }


        [Browsable(
false),
       DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never)]
        
public new DataGridViewRow RowTemplate
        
{
            
get return base.RowTemplate; }
            
set base.RowTemplate = value; }
        }


        [Description(
"Returns the TreeGridNode for the given DataGridViewRow")]
        
public TreeGridNode GetNodeForRow(DataGridViewRow row)
        
{
            
return row as TreeGridNode;
        }


        [Description(
"Returns the TreeGridNode for the given DataGridViewRow")]
        
public TreeGridNode GetNodeForRow(int index)
        
{
            
return GetNodeForRow(base.Rows[index]);
        }


        [Category(
"Data"),
        Description(
"The collection of root nodes in the treelist."),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        Editor(
typeof(CollectionEditor), typeof(UITypeEditor))]
        
public TreeGridNodeCollection Nodes
        
{
            
get
            
{
                
return this._root.Nodes;
            }

        }


        
public new TreeGridNode CurrentRow
        
{
            
get
            
{
                
return base.CurrentRow as TreeGridNode;
            }

        }


        [DefaultValue(
false),
        Description(
"Causes nodes to always show as expandable. Use the NodeExpanding event to add nodes.")]
        
public bool VirtualNodes
        
{
            
get return _virtualNodes; }
            
set { _virtualNodes = value; }
        }

    
        
public TreeGridNode CurrentNode
        
{
            
get
            
{
                
return this.CurrentRow;
            }

        }


        [DefaultValue(
true)]
        
public bool ShowLines
        
{
            
get return this._showLines; }
            
set 
                
if (value != this._showLines) {
                    
this._showLines = value;
                    
this.Invalidate();
                }
 
            }

        }

    
        
public ImageList ImageList
        
{
            
get return this._imageList; }
            
set 
                
this._imageList = value; 
            }

        }


        
public new int RowCount
        
{
            
get return this.Nodes.Count; }
            
set
            
{
                
for (int i = 0; i < value; i++)
                    
this.Nodes.Add(new TreeGridNode());
            }

        }


        
Site nodes and collapse/expand support

        
Collapse/Expand events

        
Helper methods

    }

}

TreeGridCell.cs

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Drawing;
using System.Diagnostics;

namespace DataGridTreeView
{
    
public class TreeGridCell : DataGridViewTextBoxCell
    
{
        
private const int INDENT_WIDTH = 20;
        
private const int INDENT_MARGIN = 5;
        
private int glyphWidth;
        
private int calculatedLeftPadding;
        
internal bool IsSited;
        
private Padding _previousPadding;
        
private int _imageWidth = 0;
        
private int _imageHeight = 0;
        
private int _imageHeightOffset = 0;
        
private Rectangle _lastKnownGlyphRect;

        
public TreeGridCell()
        
{
            glyphWidth 
= 15;
            calculatedLeftPadding 
= 0;
            
this.IsSited = false;
        }


        
public override object Clone()
        
{
            TreeGridCell cell 
= (TreeGridCell)base.Clone();
            cell.glyphWidth 
= this.glyphWidth;
            cell.calculatedLeftPadding 
= this.calculatedLeftPadding;

            
return cell;
        }


        
internal protected virtual void UnSited()
        
{
            
this.IsSited = false;
            
this.Style.Padding = this._previousPadding;
        }


        
internal protected virtual void Sited()
        
{
            
this.IsSited = true;
            
this._previousPadding = this.Style.Padding;
            
this.UpdateStyle();
        }


        
internal protected virtual void UpdateStyle()
        
{
            
if (this.IsSited == false)
                
return;

            
int level = this.Level;

            Padding p 
= this._previousPadding;
            Size preferredSize;

            
using (Graphics g = this.OwningNode._grid.CreateGraphics())
            
{
                preferredSize 
= this.GetPreferredSize(g, this.InheritedStyle, this.RowIndex, new Size(00));
            }


            Image image 
= this.OwningNode.Image;

            
if (image != null)
            
{
                _imageWidth 
= image.Width + 2;
                _imageHeight 
= image.Height + 2;
            }

            
else
            
{
                _imageWidth 
= glyphWidth;
                _imageHeight 
= 0;
            }


            
if (preferredSize.Height < _imageHeight)
            
{
                
this.Style.Padding = new Padding(p.Left + (level * INDENT_WIDTH) + _imageWidth + INDENT_MARGIN,
                                                 p.Top 
+ (_imageHeight / 2), p.Right, p.Bottom + (_imageHeight / 2));
                _imageHeightOffset 
= 2;
            }

            
else
            
{
                
this.Style.Padding = new Padding(p.Left + (level * INDENT_WIDTH) + _imageWidth + INDENT_MARGIN,
                                                 p.Top, p.Right, p.Bottom);
            }


            calculatedLeftPadding 
= ((level - 1* glyphWidth) + _imageWidth + INDENT_MARGIN;
        }


        
public int Level
        
{
            
get
            
{
                TreeGridNode row 
= this.OwningNode;
                
if (row != null)
                
{
                    
return row.Level;
                }

                
else
                
{
                    
return -1;
                }

            }

        }


        
public TreeGridNode OwningNode
        
{
            
get
            
{
                
return base.OwningRow as TreeGridNode;
            }

        }


        
protected virtual int GlyphMargin
        
{
            
get
            
{
                
return ((this.Level - 1* INDENT_WIDTH) + INDENT_MARGIN;
            }

        }


        
protected virtual int GlyphOffset
        
{
            
get
            
{
                
return ((this.Level - 1* INDENT_WIDTH);
            }

        }


        
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        
{

            TreeGridNode node 
= this.OwningNode;
            
if (node == nullreturn;

            Image image 
= node.Image;

            
if (this._imageHeight == 0 && image != nullthis.UpdateStyle();

            
// paint the cell normally
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);

            
// TODO: Indent width needs to take image size into account
            Rectangle glyphRect = new Rectangle(cellBounds.X + this.GlyphMargin, cellBounds.Y, INDENT_WIDTH, cellBounds.Height - 1);
            
int glyphHalf = glyphRect.Width / 2;

            
//TODO: This painting code needs to be rehashed to be cleaner
            int level = this.Level;

            
//TODO: Rehash this to take different Imagelayouts into account. This will speed up drawing
            
//        for images of the same size (ImageLayout.None)
            if (image != null)
            
{
                Point pp;
                
if (_imageHeight > cellBounds.Height)
                    pp 
= new Point(glyphRect.X + this.glyphWidth, cellBounds.Y + _imageHeightOffset);
                
else
                    pp 
= new Point(glyphRect.X + this.glyphWidth, (cellBounds.Height / 2 - _imageHeight / 2+ cellBounds.Y);

                
// Graphics container to push/pop changes. This enables us to set clipping when painting
                
// the cell's image -- keeps it from bleeding outsize of cells.
                System.Drawing.Drawing2D.GraphicsContainer gc = graphics.BeginContainer();
                
{
                    graphics.SetClip(cellBounds);
                    graphics.DrawImageUnscaled(image, pp);
                }

                graphics.EndContainer(gc);
            }


            
// Paint tree lines            
            if (node._grid.ShowLines)
            
{
                
using (Pen linePen = new Pen(SystemBrushes.ControlDark, 1.0f))
                
{
                    linePen.DashStyle 
= System.Drawing.Drawing2D.DashStyle.Dot;
                    
bool isLastSibling = node.IsLastSibling;
                    
bool isFirstSibling = node.IsFirstSibling;
                    
if (node.Level == 1)
                    
{
                        
// the Root nodes display their lines differently
                        if (isFirstSibling && isLastSibling)
                        
{
                            
// only node, both first and last. Just draw horizontal line
                            graphics.DrawLine(linePen, glyphRect.X + 4, cellBounds.Top + cellBounds.Height / 2, glyphRect.Right, cellBounds.Top + cellBounds.Height / 2);
                        }

                        
else if (isLastSibling)
                        
{
                            
// last sibling doesn't draw the line extended below. Paint horizontal then vertical
                            graphics.DrawLine(linePen, glyphRect.X + 4, cellBounds.Top + cellBounds.Height / 2, glyphRect.Right, cellBounds.Top + cellBounds.Height / 2);
                            graphics.DrawLine(linePen, glyphRect.X 
+ 4, cellBounds.Top, glyphRect.X + 4, cellBounds.Top + cellBounds.Height / 2);
                        }

                        
else if (isFirstSibling)
                        
{
                            
// first sibling doesn't draw the line extended above. Paint horizontal then vertical
                            graphics.DrawLine(linePen, glyphRect.X + 4, cellBounds.Top + cellBounds.Height / 2, glyphRect.Right, cellBounds.Top + cellBounds.Height / 2);
                            graphics.DrawLine(linePen, glyphRect.X 
+ 4, cellBounds.Top + cellBounds.Height / 2, glyphRect.X + 4, cellBounds.Bottom);
                        }

                        
else
                        
{
                            
// normal drawing draws extended from top to bottom. Paint horizontal then vertical
                            graphics.DrawLine(linePen, glyphRect.X + 4, cellBounds.Top + cellBounds.Height / 2, glyphRect.Right, cellBounds.Top + cellBounds.Height / 2);
                            graphics.DrawLine(linePen, glyphRect.X 
+ 4, cellBounds.Top, glyphRect.X + 4, cellBounds.Bottom);
                        }

                    }

                    
else
                    
{
                        
if (isLastSibling)
                        
{
                            
// last sibling doesn't draw the line extended below. Paint horizontal then vertical
                            graphics.DrawLine(linePen, glyphRect.X + 4, cellBounds.Top + cellBounds.Height / 2, glyphRect.Right, cellBounds.Top + cellBounds.Height / 2);
                            graphics.DrawLine(linePen, glyphRect.X 
+ 4, cellBounds.Top, glyphRect.X + 4, cellBounds.Top + cellBounds.Height / 2);
                        }

                        
else
                        
{
                            
// normal drawing draws extended from top to bottom. Paint horizontal then vertical
                            graphics.DrawLine(linePen, glyphRect.X + 4, cellBounds.Top + cellBounds.Height / 2, glyphRect.Right, cellBounds.Top + cellBounds.Height / 2);
                            graphics.DrawLine(linePen, glyphRect.X 
+ 4, cellBounds.Top, glyphRect.X + 4, cellBounds.Bottom);
                        }


                        
// paint lines of previous levels to the root
                        TreeGridNode previousNode = node.Parent;
                        
int horizontalStop = (glyphRect.X + 4- INDENT_WIDTH;

                        
while (!previousNode.IsRoot)
                        
{
                            
if (previousNode.HasChildren && !previousNode.IsLastSibling)
                            
{
                                
// paint vertical line
                                graphics.DrawLine(linePen, horizontalStop, cellBounds.Top, horizontalStop, cellBounds.Bottom);
                            }

                            previousNode 
= previousNode.Parent;
                            horizontalStop 
= horizontalStop - INDENT_WIDTH;
                        }

                    }


                }

            }


            
if (node.HasChildren || node._grid.VirtualNodes)
            
{            
                
if (node.IsExpanded)
                    node._grid.rOpen.DrawBackground(graphics, 
new Rectangle(glyphRect.X, glyphRect.Y + (glyphRect.Height / 2- 41010));
                
else
                    node._grid.rClose.DrawBackground(graphics, 
new Rectangle(glyphRect.X, glyphRect.Y + (glyphRect.Height / 2- 41010));
            }

        }

        
protected override void OnMouseUp(DataGridViewCellMouseEventArgs e)
        
{
            
base.OnMouseUp(e);

            TreeGridNode node 
= this.OwningNode;
            
if (node != null)
                node._grid._inExpandCollapseMouseCapture 
= false;
        }

        
protected override void OnMouseDown(DataGridViewCellMouseEventArgs e)
        
{
            
if (e.Location.X > this.InheritedStyle.Padding.Left)
            
{
                
base.OnMouseDown(e);
            }

            
else
            
{
                TreeGridNode node 
= this.OwningNode;
                
if (node != null)
                
{
                    node._grid._inExpandCollapseMouseCapture 
= true;
                    
if (node.IsExpanded)
                        node.Collapse();
                    
else
                        node.Expand();
                }

            }

        }

    }

}

TreeGridColumn.cs

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Design;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;

namespace DataGridTreeView
{
    
public class TreeGridColumn : DataGridViewTextBoxColumn
    
{
        
internal Image _defaultNodeImage;

        
public TreeGridColumn()
        
{
            
this.CellTemplate = new TreeGridCell();
        }


        
public override object Clone()
        
{
            TreeGridColumn column 
= (TreeGridColumn)base.Clone();
            column._defaultNodeImage 
= this._defaultNodeImage;

            
return column;
        }


        
public Image DefaultNodeImage
        
{
            
get
            
{
                
return _defaultNodeImage;
            }


            
set
            
{
                _defaultNodeImage 
= value;
            }

        }

    }

}

TreeGridNode.cs

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Design;
using System.Diagnostics;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;

namespace DataGridTreeView
{
    [ToolboxItem(
false),DesignTimeVisible(false)]
    
public class TreeGridNode : DataGridViewRow
    
{
        
internal TreeGridView _grid;
        
internal TreeGridNode _parent;
        
internal TreeGridNodeCollection _owner;
        
internal bool IsExpanded;
        
internal bool IsRoot;
        
internal bool _isSited;
        
internal bool _isFirstSibling;
        
internal bool _isLastSibling;
        
internal Image _image;
        
internal int _imageIndex;

        
private Random rndSeed = new Random();
        
public int UniqueValue = -1;
        TreeGridCell _treeCell;
        TreeGridNodeCollection childrenNodes;

        
private int _index;
        
private int _level;
        
private bool childCellsCreated = false;

        
private ISite site = null;
        
private EventHandler disposed = null;

        
internal TreeGridNode(TreeGridView owner)
            : 
this()
        
{
            
this._grid = owner;
            
this.IsExpanded = true;
        }


        
public TreeGridNode()
        
{
            _index 
= -1;
            _level 
= -1;
            IsExpanded 
= false;
            UniqueValue 
= this.rndSeed.Next();
            _isSited 
= false;
            _isFirstSibling 
= false;
            _isLastSibling 
= false;
            _imageIndex 
= -1;
        }


        
public override object Clone()
        
{
            TreeGridNode row 
= (TreeGridNode)base.Clone();
            row.UniqueValue 
= -1;
            row._level 
= this._level;
            row._grid 
= this._grid;
            row._parent 
= this._parent;
            row._imageIndex 
= this._imageIndex;

            
if (row._imageIndex == -1)
            
{
                row.Image 
= this.Image;
            }


            row.IsExpanded 
= this.IsExpanded;

            
return row;
        }


        
internal protected virtual void UnSited()
        
{
            TreeGridCell cell;
            
foreach (DataGridViewCell dCell in this.Cells)
            
{
                cell 
= dCell as TreeGridCell;
                
if (cell != null)
                
{
                    cell.UnSited();
                }

            }


            
this._isSited = false;
        }


        
internal protected virtual void Sited()
        
{
            
this._isSited = true;
            
this.childCellsCreated = true;
            Debug.Assert(
this._grid != null);

            TreeGridCell cell;
            
foreach (DataGridViewCell dCell in this.Cells)
            
{
                cell 
= dCell as TreeGridCell;
                
if (cell != null)
                
{
                    cell.Sited();
                }

            }

        }


        
public Image Image
        
{
            
get
            
{
                
if (_image == null && _imageIndex != -1)
                
{
                    
if (this.ImageList != null && this._imageIndex < this.ImageList.Images.Count)
                    
{
                        
return this.ImageList.Images[this._imageIndex];
                    }

                    
else
                    
{
                        
return null;
                    }

                }

                
else
                
{
                    
return this._image;
                }

            }


            
set
            
{
                _image 
= value;
                
if (_image != null)
                
{
                    
this._imageIndex = -1;
                }

                
if (this._isSited)
                
{
                    
this._treeCell.UpdateStyle();
                    
if (this.Displayed)
                    
{
                        
this._grid.InvalidateRow(this.RowIndex);
                    }

                }

            }

        }


        [System.ComponentModel.Description(
"Represents the index of this row in the Grid. Advanced usage."),
        System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced),
         Browsable(
false),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        
public int RowIndex
        
{
            
get
            
{
                
return base.Index;
            }

        }


        [Browsable(
false),
        EditorBrowsable(EditorBrowsableState.Never),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        
public ImageList ImageList
        
{
            
get
            
{
                
if (this._grid != null)
                
{
                    
return this._grid.ImageList;
                }

                
else
                
{
                    
return null;
                }

            }

        }


        [Browsable(
false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        
public new int Index
        
{
            
get
            
{
                
if (_index == -1)
                
{
                    _index 
= this._owner.IndexOf(this);
                }


                
return _index;
            }


            
internal set
            
{
                _index 
= value;
            }

        }


        
private bool ShouldSerializeImageIndex()
        
{
            
return (this._imageIndex != -1 && this._image == null);
        }


        [Category(
"Appearance"),
        Description(
"..."), DefaultValue(-1),
        TypeConverter(
typeof(ImageIndexConverter)),
        Editor(
"System.Windows.Forms.Design.ImageIndexEditor"typeof(UITypeEditor))]
        
public int ImageIndex
        
{
            
get return _imageIndex; }
            
set
            
{
                _imageIndex 
= value;
                
if (_imageIndex != -1)
                
{
                    
this._image = null;
                }

                
if (this._isSited)
                
{
                    
this._treeCell.UpdateStyle();
                    
if (this.Displayed)
                        
this._grid.InvalidateRow(this.RowIndex);
                }

            }

        }


        
private bool ShouldSerializeImage()
        
{
            
return (this._imageIndex == -1 && this._image != null);
        }


        
protected override DataGridViewCellCollection CreateCellsInstance()
        
{
            DataGridViewCellCollection cells 
= base.CreateCellsInstance();
            cells.CollectionChanged 
+= cells_CollectionChanged;
            
return cells;
        }


        
void cells_CollectionChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e)
        
{
            
if (_treeCell != nullreturn;

            
if (e.Action == System.ComponentModel.CollectionChangeAction.Add || e.Action == System.ComponentModel.CollectionChangeAction.Refresh)
            
{
                TreeGridCell treeCell 
= null;

                
if (e.Element == null)
                
{
                    
foreach (DataGridViewCell cell in base.Cells)
                    
{
                        
if (cell.GetType().IsAssignableFrom(typeof(TreeGridCell)))
                        
{
                            treeCell 
= (TreeGridCell)cell;
                            
break;
                        }


                    }

                }

                
else
                
{
                    treeCell 
= e.Element as TreeGridCell;
                }


                
if (treeCell != null)
                    _treeCell 
= treeCell;
            }

        }


        [Category(
"Data"),
         Description(
"The collection of root nodes in the treelist."),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
         Editor(
typeof(CollectionEditor), typeof(UITypeEditor))]
        
public TreeGridNodeCollection Nodes
        
{
            
get
            
{
                
if (childrenNodes == null)
                
{
                    childrenNodes 
= new TreeGridNodeCollection(this);
                }

                
return childrenNodes;
            }

            
set { ;}
        }


        [Browsable(
false),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        
public new DataGridViewCellCollection Cells
        
{
            
get
            
{
                
if (!childCellsCreated && this.DataGridView == null)
                
{
                    
if (this._grid == nullreturn null;

                    
this.CreateCells(this._grid);
                    childCellsCreated 
= true;
                }

                
return base.Cells;
            }

        }


        [Browsable(
false),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        
public int Level
        
{
            
get
            
{
                
if (this._level == -1)
                
{
                    
// calculate level
                    int walk = 0;
                    TreeGridNode walkRow 
= this.Parent;
                    
while (walkRow != null)
                    
{
                        walk
++;
                        walkRow 
= walkRow.Parent;
                    }

                    
this._level = walk;
                }

                
return this._level;
            }

        }


        [Browsable(
false),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        
public TreeGridNode Parent
        
{
            
get
            
{
                
return this._parent;
            }

        }


        [Browsable(
false),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        
public virtual bool HasChildren
        
{
            
get
            
{
                
return (this.childrenNodes != null && this.Nodes.Count != 0);
            }

        }


        [Browsable(
false)]
        
public bool IsSited
        
{
            
get
            
{
                
return this._isSited;
            }

        }

        [Browsable(
false)]
        
public bool IsFirstSibling
        
{
            
get
            
{
                
return (this.Index == 0);
            }

        }


        [Browsable(
false)]
        
public bool IsLastSibling
        
{
            
get
            
{
                TreeGridNode parent 
= this.Parent;
                
if (parent != null && parent.HasChildren)
                
{
                    
return (this.Index == parent.Nodes.Count - 1);
                }

                
else
                    
return true;
            }

        }


        
public virtual bool Collapse()
        
{
            
return this._grid.CollapseNode(this);
        }


        
public virtual bool Expand()
        
{
            
if (this._grid != null)
                
return this._grid.ExpandNode(this);
            
else
            
{
                
this.IsExpanded = true;
                
return true;
            }

        }


        
internal protected virtual bool InsertChildNode(int index, TreeGridNode node)
        
{
            node._parent 
= this;
            node._grid 
= this._grid;

            
// ensure that all children of this node has their grid set
            if (this._grid != null)
                UpdateChildNodes(node);

            
//TODO: do we need to use index parameter?
            if ((this._isSited || this.IsRoot) && this.IsExpanded)
                
this._grid.SiteNode(node);
            
return true;
        }


        
internal protected virtual bool InsertChildNodes(int index, params TreeGridNode[] nodes)
        
{
            
foreach (TreeGridNode node in nodes)
            
{
                
this.InsertChildNode(index, node);
            }

            
return true;
        }


        
internal protected virtual bool AddChildNode(TreeGridNode node)
        
{
            node._parent 
= this;
            node._grid 
= this._grid;

            
// ensure that all children of this node has their grid set
            if (this._grid != null)
                UpdateChildNodes(node);

            
if ((this._isSited || this.IsRoot) && this.IsExpanded && !node._isSited)
                
this._grid.SiteNode(node);

            
return true;
        }

        
internal protected virtual bool AddChildNodes(params TreeGridNode[] nodes)
        
{
            
//TODO: Convert the final call into an SiteNodes??
            foreach (TreeGridNode node in nodes)
            
{
                
this.AddChildNode(node);
            }

            
return true;

        }


        
internal protected virtual bool RemoveChildNode(TreeGridNode node)
        
{
            
if ((this.IsRoot || this._isSited) && this.IsExpanded)
            
{
                
//We only unsite out child node if we are sited and expanded.
                this._grid.UnSiteNode(node);

            }

            node._grid 
= null;
            node._parent 
= null;
            
return true;

        }


        
internal protected virtual bool ClearNodes()
        
{
            
if (this.HasChildren)
            
{
                
for (int i = this.Nodes.Count - 1; i >= 0; i--)
                
{
                    
this.Nodes.RemoveAt(i);
                }

            }

            
return true;
        }


        [
            Browsable(
false),
            EditorBrowsable(EditorBrowsableState.Advanced)
        ]
        
public event EventHandler Disposed
        
{
            add
            
{
                
this.disposed += value;
            }

            remove
            
{
                
this.disposed -= value;
            }

        }


        [
            Browsable(
false),
            DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
        ]
        
public ISite Site
        
{
            
get
            
{
                
return this.site;
            }

            
set
            
{
                
this.site = value;
            }

        }


        
private void UpdateChildNodes(TreeGridNode node)
        
{
            
if (node.HasChildren)
            
{
                
foreach (TreeGridNode childNode in node.Nodes)
                
{
                    childNode._grid 
= node._grid;
                    
this.UpdateChildNodes(childNode);
                }

            }

        }


        
public override string ToString()
        
{
            StringBuilder sb 
= new StringBuilder(36);
            sb.Append(
"TreeGridNode { Index=");
            sb.Append(
this.RowIndex.ToString(System.Globalization.CultureInfo.CurrentCulture));
            sb.Append(
" }");
            
return sb.ToString();
        }


        
//protected override void Dispose(bool disposing) {
        
//    if (disposing)
        
//    {
        
//        lock(this)
        
//        {
        
//            if (this.site != null && this.site.Container != null)
        
//            {
        
//                this.site.Container.Remove(this);
        
//            }

        
//            if (this.disposed != null)
        
//            {
        
//                this.disposed(this, EventArgs.Empty);
        
//            }
        
//        }
        
//    }

        
//    base.Dispose(disposing);
        
//}
    }

}

TreeGridNodeCollection.cs

 

using System;
using System.Collections.Generic;
using System.Text;

namespace DataGridTreeView
{
    
public class TreeGridNodeCollection : System.Collections.Generic.IList<TreeGridNode>, System.Collections.IList
    
{
        
internal System.Collections.Generic.List<TreeGridNode> _list;
        
internal TreeGridNode _owner;
        
internal TreeGridNodeCollection(TreeGridNode owner)
        
{
            
this._owner = owner;
            
this._list = new List<TreeGridNode>();
        }


        
Public Members

        
IList Interface

        
ICollection Members
    }

}

TreeGridEvents.cs

 

using System;
using System.Collections.Generic;
using System.Text;

namespace DataGridTreeView
{
    
public class TreeGridNodeEventBase
    
{
        
private TreeGridNode _node;

        
public TreeGridNodeEventBase(TreeGridNode node)
        
{
            
this._node = node;
        }


        
public TreeGridNode Node
        
{
            
get return _node; }
        }

    }


    
public class CollapsingEventArgs : System.ComponentModel.CancelEventArgs
    
{
        
private TreeGridNode _node;

        
private CollapsingEventArgs() { }

        
public CollapsingEventArgs(TreeGridNode node)
            : 
base()
        
{
            
this._node = node;
        }


        
public TreeGridNode Node
        
{
            
get return _node; }
        }

    }


    
public class CollapsedEventArgs : TreeGridNodeEventBase
    
{
        
public CollapsedEventArgs(TreeGridNode node)
            : 
base(node)
        
{
            
//TODO
        }

    }


    
public class ExpandingEventArgs : System.ComponentModel.CancelEventArgs
    
{
        
private TreeGridNode _node;

        
private ExpandingEventArgs() { }

        
public ExpandingEventArgs(TreeGridNode node)
        
{
            
this._node = node;
        }


        
public TreeGridNode Node
        
{
            
get return _node; }
        }

    }


    
public class ExpandedEventArgs : TreeGridNodeEventBase
    
{
        
public ExpandedEventArgs(TreeGridNode node)
            : 
base(node)
        
{
            
//TODO
        }

    }


    
public delegate void ExpandingEventHandler(object sender, ExpandingEventArgs e);
    
public delegate void ExpandedEventHandler(object sender, ExpandedEventArgs e);

    
public delegate void CollapsingEventHandler(object sender, CollapsingEventArgs e);
    
public delegate void CollapsedEventHandler(object sender, CollapsedEventArgs e);
}

SimpleTestApp.cs

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DataGridTreeView;

namespace SimpleTestApp
{
    
public partial class Form1 : Form
    
{
        
private TreeGridView treeGridView1;
        
private System.Windows.Forms.DataGridViewImageColumn attachmentColumn;
        
private TreeGridColumn subjectColumn;
        
private System.Windows.Forms.DataGridViewTextBoxColumn fromColumn;
        
private System.Windows.Forms.DataGridViewTextBoxColumn dateColumn;

        
public Form1()
        
{
            InitializeComponent();
            treeGridView1 
= new TreeGridView();

            
this.attachmentColumn = new System.Windows.Forms.DataGridViewImageColumn();
            
this.attachmentColumn.HeaderText = "Attachment";
            
this.subjectColumn = new TreeGridColumn();
            
this.subjectColumn.HeaderText = "Subject";
            
this.fromColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
            
this.fromColumn.HeaderText = "From";
            
this.dateColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
            
this.dateColumn.HeaderText = "Date";

            
this.treeGridView1.AllowUserToAddRows = false;
            
this.treeGridView1.AllowUserToDeleteRows = false;
            
this.treeGridView1.AllowUserToOrderColumns = true;
            
//this.treeGridView1.ShowLines = false;
            this.treeGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        
| System.Windows.Forms.AnchorStyles.Left)
                        
| System.Windows.Forms.AnchorStyles.Right)));
            
this.treeGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
            
this.treeGridView1.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;
            
//this.treeGridView1.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.None;
            this.treeGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
            
this.attachmentColumn,
            
this.subjectColumn,
            
this.fromColumn,
            
this.dateColumn}
);

            
this.treeGridView1.Size = new Size(700450);
            
            
this.Controls.Add(treeGridView1);
        }


        
private void Form1_Load(object sender, EventArgs e)
        
{
            Font boldFont 
= new Font(treeGridView1.DefaultCellStyle.Font, FontStyle.Bold);

            TreeGridNode node 
= treeGridView1.Nodes.Add(null"Using DataView filter when binding to DataGridView""tab"@"10/19/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Nodes.Add(null"Re: Using DataView filter when binding to DataGridView""tab"@"10/19/2005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"Using CurrencyManager's ItemChanged Event correctly""michael"@"11/27/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Nodes.Add(null"Re: Using CurrencyManager's ItemChanged Event correctly""tab"@"10/19/2005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"updgrade vb6 to .net adodc""howie"@"11/27/2005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"threads for reading data to textarea""ajijv"@"11/20/2005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"SQL Server and DataSet bound to DataGridView""tab"@"11/20/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Nodes.Add(null"Re: SQL Server and DataSet bound to DataGridView""Bart Mermuys"@"10/19/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"SQL Server timeout""sybn"@"11/7/2005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"Selecting rows in the DataGrid""jez"@"10/3/2005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"Referring to boundfields properties""mikeslaptop"@"10/17/2005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"NEWBIE with database connection error"@"No_So_Clever"@"10/24/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Nodes.Add(null"Re: NEWBIE with database connection error""Jerry H"@"10/31/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"Referring to boundfields properties""mikeslaptop"@"10/17/2005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"Partial load of data""james"@"10/19/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"Master-details query""pinerallo"@"10/29/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"How to access a datagrid column""mervin"@"11/1/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"Empty table""guy"@"10/26/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"Deepbinding: ICustomTypeDescriptor problem"@"kpax"@"10/12/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Nodes.Add(null"Re: Deepbinding: ICustomTypeDescriptor problem""Mervin"@"10/31/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Parent.Nodes.Add(null"Re: Deepbinding: ICustomTypeDescriptor problem""Jerry H"@"10/31/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Nodes.Add(null"Re: Deepbinding: ICustomTypeDescriptor problem""james"@"10/31/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Nodes.Add(null"Re: Deepbinding: ICustomTypeDescriptor problem""Mark"@"10/31/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Parent.Nodes.Add(null"Re: Deepbinding: ICustomTypeDescriptor problem""Jerry H"@"10/31/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"Datasource propert in usercontrol""mamaike"@"10/23/32005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"DataGridView insert record""Stephen"@"11/24/32005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"GridView null values""Stanislav Nedelchev"@"11/29/32005 1:02 AM");
            node.ImageIndex 
= 1;

            node 
= treeGridView1.Nodes.Add(null@"Current position""No_So_Clever"@"11/8/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"ComboBox inside of datgrid""Rick"@"11/24/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"Quick question about datagrid""Sowen"@"11/14/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
            node 
= node.Nodes.Add(null"Re: Quick question about datagrid""Jerry H"@"10/31/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"Best single documentation source for Binding""Michael"@"11/2/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;

            node 
= treeGridView1.Nodes.Add(null@"Bind dataset to crystal report""Sanjeewa"@"11/24/2005 1:02 AM");
            node.ImageIndex 
= 0;
            node.DefaultCellStyle.Font 
= boldFont;
        }

    }

}