Click here to Skip to main content
Click here to Skip to main content

TreeListView

By , 31 Aug 2003
 

Introduction

The System.Windows.Forms namespace provides the ListView and TreeView controls. But there is no control that allows you to use a tree and columns together.

I made such a control that enables this features:

  • Ties a ListView and a TreeView together in a TreeListView class that includes BeforeExpand, AfterExpand, BeforeCollapse, AfterCollapse events,
  • Uses a TreeListViewItem class that includes Expand function, Collapse functions, IsExpanded property,
  • Uses a TreeListViewItemCollection that replaces the ListViewItemCollection class used in the ListView control. This class is also used for the Items property in the TreeListViewItem class that contains the childs of an item. TreeListViewItemCollection adds the Sort function capability,
  • Subitem edit with custom control (EditBox, ComboBox, etc...),
  • XP-Style selection,
  • Plus-minus boxes and lines,
  • Indeterminate state item.

TreeListView control

This class inherits from the ListView class.

Properties

Some properties have been changed:

For example, the View property of the ListView control is no more used and must always be equal to View.Details. The Items is now a TreeListViewItemCollection. The SelectedItems and CheckedItems are now TreeListViewItem arrays (I don't have make special collection like SelectedListViewItemCollection and CheckedListViewItemCollection for the original ListView class...).

public new TreeListView.TreeListViewItemCollection Items{
    get{return(_items);}}

new public SelectedTreeListViewItemCollection SelectedItems
{
    get
    {
          SelectedTreeListViewItemCollection sel = new 
                                     SelectedTreeListViewItemCollection(this);
        return(sel);
    }
}
public new TreeListViewItem[] CheckedItems
{
    get
    {
        TreeListViewItem[] array = new 
                                  TreeListViewItem[base.CheckedIndices.Count];
        for(int i = 0 ; i < base.CheckedIndices.Count ; i++)
            array[i] = (TreeListViewItem) base.CheckedItems[i];
        return(array);
    }
}

// Gets the informations of the current edited item
public EditItemInformations EditedItem
{
    get{return _editeditem;}
}

// Gets wether an item is currently edited
public bool InEdit
{
    get{return _inedit;}
}

// Gets or sets a value indicating whether plus-sign (+) and minus-sign (-) 
// buttons are displayed next to TreeListView that contain child TreeListViews
public bool ShowPlusMinus
{
    get{return _showplusminus;}
    set{if(_showplusminus == value) return;
        _showplusminus = value;
        if(Created) Invoke(new VoidHandler(VisChanged));}
}

// Gets or Sets the color of the lines if ShowPlusMinus property is enabled
public Color PlusMinusLineColor
{
    get{return _plusMinusLineColor;}
    set{_plusMinusLineColor = value;
        if(Created) Invalidate();}
}

// Gets or Sets whether the control draw XP-Style highlight color
public bool UseXPHighlightStyle
{
    get{return _useXPHighLightStyle;}
    set{_useXPHighLightStyle = value;
        if(Created) Invalidate();}
}

Expand and collapse events

Like in the TreeView, when an item is expanded or collapsed, an event is raised before and after.
New events replace the AfterLabelEdit and BeforeLabelEdit of the standard ListView class. They allow you to modify the column to edit and the control that is used to edit the subitem (TextBox, ComboBox for example).

Here is a list of the new events (the handlers and arguments are not described here) :

[Description("Occurs before the tree node is collapsed")]
public event TreeListViewCancelEventHandler BeforeExpand;

[Description("Occurs before the tree node is collapsed")]
public event TreeListViewCancelEventHandler BeforeCollapse;

[Description("Occurs after the tree node is expanded")]
public event TreeListViewEventHandler AfterExpand;

[Description("Occurs after the tree node is collapsed")]
public event TreeListViewEventHandler AfterCollapse;

[Description("Occurs when the label for an item is edited by the user.")]
public new event TreeListViewLabelEditEventHandler AfterLabelEdit;

[Description("Occurs when the user starts editing the label of an item.")]
public new event TreeListViewBeforeLabelEditEventHandler BeforeLabelEdit;

TreeListViewItem class

This class inherits from the ListViewItem class. Some methods and properties have been changed like in the TreeListView class but the most important functions are the Expand and Collapse functions.

The Expand function adds each child of the collection in descending order just after this TreeListViewItem, so that the first item of the child appears just after the parent, the second after the first, etc.. because the expansion adds each child just after the parent item.

The Collapse function removes each child in the items from the ListView.

private bool _isexpanded;
public bool IsExpanded{
    get{return(_isexpanded);}}

public void Expand()
{
    if(ListView != null)
        if(ListView.InvokeRequired)
            throw(new Exception("Invoke Required"));
    // The item wasn't expanded -> raise an event
    if(Visible && !_isexpanded && ListView != null)
    {
         TreeListViewCancelEventArgs e = new TreeListViewCancelEventArgs(
            this, TreeListViewAction.Expand);
         ListView.RaiseBeforeExpand(e);
         if(e.Cancel) return;
    }
    if(Visible)
        for(int i = Items.Count - 1 ; i >= 0 ;i--)
        {
            TreeListViewItem item = this.Items[i];
            if(!item.Visible)
            {
                ListView LView = this.ListView;
                LView.Items.Insert(
                    this.Index + 1,
                    item);
                item.SetIndentation();
            }
            if(item.IsExpanded)
                item.Expand();
        }
    // The item wasn't expanded -> raise an event
    if(Visible && !_isexpanded && ListView != null)
    {
        this._isexpanded = true;
        TreeListViewEventArgs e = new TreeListViewEventArgs(
            this, TreeListViewAction.Expand);
        ListView.RaiseAfterExpand(e);
        if(AfterExpand != null) AfterExpand(this);
    }
    this._isexpanded = true;
}

public void Collapse()
{
    if(ListView != null)
        if(ListView.InvokeRequired)
            throw(new Exception("Invoke Required"));
    // The item was expanded -> raise an event
    if(Visible && _isexpanded && ListView != null)
    {
        TreeListViewCancelEventArgs e = new TreeListViewCancelEventArgs(
            this, TreeListViewAction.Collapse);
        ListView.RaiseBeforeCollapse(e);
        if(e.Cancel) return;
    }

    // Collapse
    if(this.Visible)
        foreach(TreeListViewItem item in Items)
                item.Hide();
    
    // The item was expanded -> raise an event
    if(Visible && _isexpanded && ListView != null)
    {
        this._isexpanded = false;
        TreeListViewEventArgs e = new TreeListViewEventArgs(
            this, TreeListViewAction.Collapse);
        ListView.RaiseAfterCollapse(e);
        if(AfterCollapse != null) AfterCollapse(this);
    }
    this._isexpanded = false;
}

The item is indented with the SetIndentation function that uses the Level property (gets the level of the item by getting the number of parents in the hierarchy) :

public int Level
{
    get{return(this.Parent == null ? 0 : this.Parent.Level + 1);}
}

public void SetIndentation()
{
    if(this.ListView == null) return;
    LV_ITEM lvi = new LV_ITEM();
    lvi.iItem = this.Index;
    lvi.iIndent = this.Level;
    if(TreeListView.ShowPlusMinus) lvi.iIndent++;
    lvi.mask = ListViewMessages.LVIF_INDENT;
    SendMessage(
        this.ListView.Handle,
        ListViewMessages.LVM_SETITEM,
        0,
        ref lvi);
}

TreeListViewItemCollection class

This class works like the TreeNodeCollection does with some changes. To manipulate items that are in a TreeListView, you must use the Invoke function if you are using multiple threads as with a standard ListView control.

Properties

The class has a Parent property (TreeListViewItem) and a Owner property (TreeListView). These properties can not have both a not null value at the same time because a collection enumerates the children of a TreeListView or enumerates the children of a TreeListViewItem. Both properties allow only to Get the value because these values are only changed internal when the constructor is called.

There are two properties SortOrder and SortOrderRecursively that get or set the sort order of the collection and automatically call the Sort function that is described below if the sort order is changed. The SortOrderRecursively property calls the SortOrder property of each TreeListViewItemCollection in the items of this collection recursively.

Functions

The Add function inserts an item in the collection at an index depending on the SortOrder value. This index is calculated with the GetInsertCollectionIndex function that is not given here. The item is also naturally inserted in the TreeListView if necessary at an index calculated with the GetInsertTreeListViewIndex function.

public virtual int Add(TreeListViewItem item)
{
    if(TreeListView != null)
        if(TreeListView.InvokeRequired)
            throw(new Exception("Invoke required"));
    // Do not add the item if the collection owns a TreeListView 
    // recursively and the item already owns a TreeListView
    if(TreeListView != null && item.ListView != null)
        throw(new Exception("The Item is already in a TreeListView"));
    int index = GetInsertCollectionIndex(item);
    if(index == -1) return(-1);
    if(Parent != null) item.SetParent(Parent);
    item.Items.Comparer = this.Comparer;
    int treelistviewindex = GetInsertTreeListViewIndex(item, index);
    // Insert in the ListView
    if(treelistviewindex > -1)
    {
        ListView listview = (ListView) TreeListView;
        listview.Items.Insert(treelistviewindex, (ListViewItem) item);
        if(item.IsExpanded) item.Expand();
        item.SetIndentation();
    }
    // Insert in this collection
    if(index > -1) List.Insert(index, item);
    if(index > -1) OnItemAdded(new TreeListViewEventArgs(item, 
                                                 TreeListViewAction.Unknown));
    return(index);
}

The Remove function removes an item from the collection.

public virtual void Remove(TreeListViewItem item)
{
    if(TreeListView != null)
        if(TreeListView.InvokeRequired)
            throw(new Exception("Invoke required"));
    int index = GetIndexOf(item);
    if(index == -1) return;
    RemoveAt(index);
}
public new void RemoveAt(int index)
{
    if(TreeListView != null)
        if(TreeListView.InvokeRequired)
            throw(new Exception("Invoke required"));
    TreeListViewItem item = this[index];
    if(this[index].Visible && this.TreeListView != null) item.Hide();
    List.RemoveAt(index);
    item.SetParent(null);
    OnItemRemoved(new TreeListViewEventArgs(item, 
                                                 TreeListViewAction.Unknown));
}

Other functions that not described here : AddRange, Clear, Contain.

The Sort function sorts the items in the collection and also change the order in the TreeListView if the items were visible. The items are stored in an array, the items in the array are sorted using the TreeListViewItemCollectionComparer class (not described here), the items are removed from the collection, and the items are copied from the sorted array to the collection.

public void Sort(bool recursively)
{
    if(TreeListView != null)
        if(TreeListView.InvokeRequired)
            throw(new Exception("Invoke required"));
    // Gets an array of the items
    TreeListViewItem[] thisarray = ToArray();
    // Removes the items
    Clear();
    // Adds the items
    foreach(TreeListViewItem item in thisarray)
        Add(item);
    if(recursively)
        foreach(TreeListViewItem item in thisarray)
            item.Items.Sort(true);
}

Other functions description

Subitem edit

To edit subitems, the control handles the LVN_BEGINLABELEDIT and LVN_ENDLABELEDIT messages in the WndProc :

case APIsEnums.ListViewNotifications.BEGINLABELEDIT:
    System.Diagnostics.Debug.Assert(FocusedItem != null);
    // Cancel label edit if the message is sent just after a double click
    if(_lastdoubleclick.AddMilliseconds(450) > DateTime.Now)
    {
        Message canceledit = Message.Create(Handle, 
                             (int) APIsEnums.ListViewMessages.CANCELEDITLABEL, 
                             IntPtr.Zero, IntPtr.Zero);
        WndProc(ref canceledit);
        m.Result = (IntPtr) 1;
        return;
    }
    item = FocusedItem;
    int column = 0;
    if(_lastitemclicked.Item == item &&
        _lastitemclicked.CreationTime.AddMilliseconds(
                          2*SystemInformation.DoubleClickTime) > DateTime.Now)
        column = _lastitemclicked.ColumnIndex;
    if(column == -1) column = 0;
    // Add subitems if needed
    while(item.SubItems.Count-1 < column) item.SubItems.Add("");
    TreeListViewBeforeLabelEditEventArgs beforeed = new 
                                         TreeListViewBeforeLabelEditEventArgs(
                                         FocusedItem, column, 
                                         item.SubItems[column].Text);
    OnBeforeLabelEdit(beforeed);
    if(beforeed.Cancel)
    {
        Message canceledit = Message.Create(Handle, 
                              (int)APIsEnums.ListViewMessages.CANCELEDITLABEL, 
                              IntPtr.Zero, IntPtr.Zero);
        WndProc(ref canceledit);
        m.Result = (IntPtr) 1;
        return;
    }
    _inedit = true;
    // Get edit handle
    Message mess = Message.Create(Handle, 
                               (int)APIsEnums.ListViewMessages.GETEDITCONTROL, 
                               IntPtr.Zero, IntPtr.Zero);
    WndProc(ref mess);
    IntPtr edithandle = mess.Result;
    _customedit = new CustomEdit(edithandle, this, beforeed.Editor);
    _editeditem = new EditItemInformations(
                     FocusedItem, beforeed.ColumnIndex, 
                             FocusedItem.SubItems[beforeed.ColumnIndex].Text);
    m.Result = IntPtr.Zero;
    return;
case APIsEnums.ListViewNotifications.ENDLABELEDIT:
    if(_customedit != null)
        _customedit.HideEditControl();
    _customedit = null;
    _inedit = false;
    _editeditem = new EditItemInformations();
    m.Result = IntPtr.Zero;
    return;

The CustomEdit class is not described here. This class will receive all messages sent to the edit box. It handles the messages and show the custom control instead of the standard edit box of the ListView.

XP-style selection

When the LVN_CUSTOMDRAW message is sent, the function CustomDraw is called to customize the draw behavior. At the pre-paint state, the select flag is set to false and the back color of the selected item is modified so that it will be displayed with a custom color.

private void CustomDraw(ref Message m)
{
  int iRow, iCol; bool bSelected;
  unsafe
  {
    APIsStructs.NMLVCUSTOMDRAW * nmlvcd = 
                          (APIsStructs.NMLVCUSTOMDRAW *)m.LParam.ToPointer();

     switch((APIsEnums.CustomDrawDrawStateFlags)nmlvcd->nmcd.dwDrawStage)
     {
       case APIsEnums.CustomDrawDrawStateFlags.PREPAINT:
              m.Result = 
                       (IntPtr)APIsEnums.CustomDrawReturnFlags.NOTIFYITEMDRAW;
              break;
       case APIsEnums.CustomDrawDrawStateFlags.ITEMPREPAINT:
              m.Result =
                    (IntPtr)APIsEnums.CustomDrawReturnFlags.NOTIFYSUBITEMDRAW;
              break;

       case APIsEnums.CustomDrawDrawStateFlags.ITEMPREPAINT |
              APIsEnums.CustomDrawDrawStateFlags.SUBITEM:
              iRow = (int)nmlvcd->nmcd.dwItemSpec;
              iCol = (int)nmlvcd->iSubItem;
              bSelected = base.Items[iRow].Selected;// && this.Focused;
              if(bSelected && _useXPHighLightStyle)
              {
                Color color = Focused ? ColorUtil.VSNetSelectionColor : 
                                       ColorUtil.VSNetSelectionUnfocusedColor;
                if(HideSelection && !Focused) color = BackColor;
                if(FullRowSelect || iCol == 0)
                   nmlvcd->clrTextBk = (int)ColorUtil.RGB(color.R, color.G, 
                                         color.B);
                   nmlvcd->nmcd.uItemState &= 
                           ~(uint)APIsEnums.CustomDrawItemStateFlags.SELECTED;
                if(iCol == 0) DrawSelectedItemFocusCues(iRow);
              }
              if(iCol == 0)
              {
                 DrawIntermediateStateItem((TreeListViewItem)base.Items[iRow]);
                 DrawPlusMinusItemLines((TreeListViewItem)base.Items[iRow]);
                 DrawPlusMinusItem((TreeListViewItem)base.Items[iRow]);
              }
              m.Result = (IntPtr)APIsEnums.CustomDrawReturnFlags.NEWFONT;
              break;
        }
    }
}

The ColorUtil class has been written by Carlos H. Perez.

The DrawIntermediateStateItem, DrawPlusMinusItemLines, DrawPlusMinusItem are not described here.

Indeterminate state item

The property Checkable avoids checking an item. An item that has this property set to true will display a grey box if at least one of the sub items is checked.

new public CheckState Checked
{
   get
   {
     if(!Checkable) return HasCheckedChild ? CheckState.Indeterminate : 
                                                         CheckState.Unchecked;
     else return(base.Checked ? CheckState.Checked : CheckState.Unchecked);
   }
   set
   {
     if(ListView != null)
     if(ListView.FreezeCheckBoxes) return;
     if(Checkable && value == CheckState.Indeterminate) 
        throw(new Exception(
              "A checkable item can only have checked and unchecked values"));
        if(Checkable)
    try{base.Checked = value == CheckState.Checked;}
    catch{}
    if(Items.Count > 0 && !Checkable)
    {
      CheckState checkvalue = value == CheckState.Unchecked ?
               CheckState.Unchecked : CheckState.Checked;
        if(ListView != null)
        {ListView.Invoke(
             new ChangeChildrenCheckStateRecursivelyHandler(
                                         ChangeChildrenCheckStateRecursively),
                                 new object[]{checkvalue});}
        else
             ChangeChildrenCheckStateRecursively(checkvalue);
        }
    }
}

Conclusion

Most of the functionalities have been described here.

I do not guarantee that this control works 100%. If you find mistakes, you can correct them. This control is not a final release and you can send me mails with explains if you find bugs or mistakes and join the modifications if you did them.

The objective is to give a good starting point for those which want to have a control which mixes the TreeView and the ListView controls.

History

  • 1 Sep 03
    • Multiselect added
    • PathSeparator added
    • Better key integration (for Multiselect and checkboxes)
    • ImageList bug fixed (better integration in the designer)
    • Scrollable bug fixed
    • Minor bugs fixed
  • 14 July 03 - updated source code
  • 7 July 2003 - updated source code.
  • 24 June 2003 - updated source code.
  • 3 Jun 2003:
    • many bugs fixed,
    • Subitem edit with custom control (EditBox, ComboBox, etc...) function,
    • XP-Style selection function,
    • Plus-minus boxes and lines function,
    • Indeterminate state item function.
  • 26 Nov 2002 - updated downloads

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

Thomas Caudal
Web Developer
France France
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionhow can i use this in my project?membermariuskraemer1 Jun '12 - 2:46 
how can i use this in my project?
QuestionPlease give me a hand. Thanks.memberChi_Chan4 Apr '12 - 22:16 
Hello, Mr. Thomas Caudal:
 
Good day.
 
First, I appreciated your free and open source TreeListView. And now I used it in my c# project, and worked fine with XP environment.
 
At the moment, I have some troubles in Win7 (32bit environment) when I use TreeListView.
 
when I click ItemEditor in the TreeListView,
1. small icon was gone.
2. no event can be trig after leaving ItemEditor.
 
Please do me a favor.
 
May I have your email address so I could send my questions and attach some images(screen shot) for your reference? So you will be clear what I mentioned.
 
Any help will be highly appreciated. Also, I am looking forward to receiving your early reply.
 
Thanks a lot.
 
Have a nice day
 
Mr. Chi-Chan in Taipei, Taiwan
QuestionTextBox instead of ComboBoxmemberJANARDHAN GURRAM20 Mar '12 - 7:56 
When iam assigning the textbox to a cell instead of combobox(in beforeLabelEditEvent)..
its not storing the value changed in the textbox in to the cell(like in combobox case)
how to do that????
//iam using this code in beforelabeleditevent
 
label b= new label ();
e.Editor=b;
JANARDHAN

BugBug when use AfterLabelEditmemberconecine12 Jan '12 - 14:47 
internal void ExitEdit(bool Cancel, string Text)
{
    //...
    //...
    base.WndProc(ref m);
    //... Bug come out: here, EditedItem==Null
    //...
    if(!Cancel)
    {
        TreeListViewLabelEditEventArgs e = new TreeListViewLabelEditEventArgs(EditedItem.Item, EditedItem.ColumnIndex, Text);
        OnAfterLabelEdit(e);
    //...
    }
    //...
}

Bugimages referred by imagekey won't be displayed if the item is added before the control is shownmemberAlex968725 Nov '11 - 4:50 
since the smallimagelist of the underlying listview is only set in onVisibleChanged, the listview doesn't know the imagelist, when you add the item before the control is shown (ie visible has changed)
 
the problem only occours, when using imagekey (not with imageindex)
 
you can fix this by adding this line:
 
new public ImageList SmallImageList
{
  get
  {
    return _smallimaglist;
  }
  set
  {
    _smallimaglist = value;
    
    //add this line
    base.SmallImageList = this._smallimaglist;
  }
}
 
Thanks for your work!
 
Br,
Alex
Question64-bit compatibility?memberRobin Reyes18 Aug '11 - 9:18 
Hello,
 
I've been using the TreeListView for years now (that's how well it worked!) but these days the new Windows systems are 64-bit.
 
The problem is whenever I double click on a TreeListView item for editing in a 64-bit machine, the program crashes since it was only made for 32-bit, I guess.
 
Is there any way to make this TreeListView compatible with 64-bit? Please post a solution if you know the answer.
 
It'd be greatly appreciated or else I will not be able to use TreeListView anymore Frown | :(
 
Thank you.
AnswerRe: 64-bit compatibility?memberRobin Reyes18 Aug '11 - 9:31 
Figured it out from an older post. (I should've looked for it first...DUH!)
 
In file APIsStructs.cs
Change structure
public struct NMHDR
{
public IntPtr hwndFrom;
public int idFrom;
public int code;
}
 
to
 
public struct NMHDR
{
public IntPtr hwndFrom;
public IntPtr idFrom;
public int code;
}
 
Remove the reference to the old TreeListView.dll and then re-add it to the project, rebuild, run, and voila. WOOHOO! Smile | :)
QuestionHow to change the color of the column HeadermemberNorth 20094 Aug '11 - 1:42 
Hi,
How to change the colour of the column header for the treelistview control.
Thanks in advance.
QuestionHow to show vertical scrollbars at right side.memberNorth 20092 Aug '11 - 0:09 
Thank you for your nice article.
Can you let me know how to show vertical scrollbars at right side of the control instead at the left side.
Thank you once again.
GeneralThe plus/minus signs not shown with the program if I rebuild it [modified]memberMember 27711384 Apr '11 - 15:04 
Hi,
 
Thank you for the nice program. I built the project using VS .NET 2008, and built the program TryTreeListView2002. If I ran the program that I just built, the plus/minus signs in front of each not were not shown up. As the result, I could not expand/collapes each node by clicking on the plus/minus signs. If I run the executable demo that downloaded from the website, I can see the plus/minus signs.
 
I ran the VS 2008 on Windows 7. I found that I could click on the empty space before the checkbox and they were expanding/collapsing. So I am sure that the plus/minus signs were invisuable. I guess the color were not correct.
 
Is there a way to fix it?
 
Thank you!

modified on Monday, April 4, 2011 9:18 PM

GeneralRe: The plus/minus signs not shown with the program if I rebuild itmemberNorth 200931 Jul '11 - 19:32 
hi,
 
I'm also facing the same problem. Is it fixed. If yes, please guide me. Thank you.
GeneralRe: The plus/minus signs not shown with the program if I rebuild itmemberNorth 20093 Aug '11 - 22:31 
Please find the solution in this forum itself with subject "Re: Tree not indent when using VS 2008..." by frobozzdamad
 

It's not a version problem. It's a bug in the control itself.

The control NEEDS the SmallImageList property set. It uses the ImageSize property of that to draw the plus-signs, root lines and indent correctly. I saw the same problem when I imported it to my project, but was wondering "why does the test project still look fine? That got converted too..."
AnswerRe: The plus/minus signs not shown with the program if I rebuild it [modified]--Resolvedmemberpurab15 Dec '11 - 21:11 
HI,
The issue can be resolved using the steps mentioned already in the above post
64-bit compatibility?
Robin Reyes 3:01 19 Aug '11

 
Anyhow just replace the following:
 
In file APIsStructs.cs
 
Change structure
public struct NMHDR
{
public IntPtr hwndFrom;
public int idFrom;
public int code;
}
 
to
 
public struct NMHDR
{
public IntPtr hwndFrom;
public IntPtr idFrom;
public int code;
}
QuestionHow to select a parent item during collapsingmemberSkynet8723 Mar '11 - 0:41 
I have a problem with selecting item. I wanto to select a visible parent when child is hiding during collapsing. I've written this:
 
private void treePPE_BeforeCollapse(object sender, TreeListViewCancelEventArgs e)
        {
            //TO DO
            if (treePPE.SelectedItems.Count > 0)
            {
                
                //treePPE.SelectedItems[0].Selected = false;
                if(IsParent(treePPE.SelectedItems[0], e.Item))
                {
                    
                    while (treePPE.SelectedItems[0] != e.Item)
                    {
                        treePPE.SelectedItems[0].PrevVisibleItem.Selected = true;
                    }
                    treePPE_Click(this, null);
                    
                }
            }
        }
 
but it doesn't work. Function IsParent checks if second item is parent of first. In my function parent does mean item is in hierarchy of item. Can anyone help with this?
GeneralBUG while changing system Timemembermansshah8 Mar '11 - 6:29 
Hi,
I found an issue with this control. If you change system time and then try to select TreeListviewitem, you are not able to select the same. what ever you try your are not able to select tree node.
 
I think this control is not handling windows message properly.
 
All ideas and suggestions to fix the same are welcomed !!!
 
Thanks,
Mansshah
GeneralProblem with EndEditmemberArchan_gel@mail.ru29 Sep '10 - 23:45 
protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
       case (int)APIsEnums.WindowMessages.KEYDOWN: 
...
Replase
protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
       case (int)APIsEnums.WindowMessages.KEYUP:
...
 
End edit Enter!
QuestionListviewItem do not have indent as treeview and show as a regualr listviewmemberJacky Chi Ho Lau22 Jul '10 - 3:35 
Hi
 
I am testing TreeListView. When i try to create a TreeListView with the same code as implement in you excample.
 
I get the problem with the TreeListViewItem, that not show in the treeview posistion with a indent in the treeview. It show as a listview.
 
Can't see any spesial properties that i has not set. Please give me some guideline.
 
The application is looking identical as available in source, but behave not the same
 
Hope for positiv answer
 
Kind regards
Chi
Questiontlv1.items.add does nothing [modified]memberFecotrentini27 Apr '10 - 2:47 
Good Morning,
 
I had no problem changing from ListView to TreeListView, instead I´m facing a big problem with items.add method.
 
I just use tlv1.items.add("test"); and it does nothing, my string doesn´t appears on TreeListView. The error message says: "Invoke Required".
 

I loaded the APIs2002 and TreeListView2002 on my project and did all the references.
 
Thanks for the help.

modified on Tuesday, April 27, 2010 9:32 AM

QuestionItem flickeringmemberSauls30 Mar '10 - 12:01 
Hello,
 
I would like to ask , how can I remove a treenode item fleekering, I have managed to remove a listview flickering by using this code and trying tree node but without luck:
 
class DoubleBufferedTreeListView : TreeListView
    {
        public DoubleBufferedTreeListView()
        {
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.EnableNotifyMessage, true);
        }
 
        protected override void OnNotifyMessage(Message m)
        {
            if (m.Msg != 0x14)
            {
                base.OnNotifyMessage(m);
            }
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            if (GetStyle(ControlStyles.UserPaint))
            {
                Message m = new Message();
                m.HWnd = Handle;
                m.Msg = 0x0318;
                m.WParam = e.Graphics.GetHdc();
                m.LParam = (IntPtr)0x00000004;
                DefWndProc(ref m);
                e.Graphics.ReleaseHdc(m.WParam);
            }
            base.OnPaint(e);
        }
    }

AnswerRe: Item flickeringmemberPaw Jershauge30 Mar '10 - 12:48 
When do you experience the flickering ?? when adding nodes or ?
 
Are you using BeginUpdate and EndUpdate methods when working with the tree ??
With great code, comes great complexity, so keep it simple stupid...Shucks | :-> Shucks | :->

GeneralRe: Item flickeringmemberSauls31 Mar '10 - 3:37 
well when I add a new node, so it's releated to a thread, every item has its own thread wich updates its information, also background color icons etc. so when I have a really big list, and when threads are updating its item it flickers, the code above fixes listview items to be steady, I only expierience the treeview lines flicker. BeginUpdate() and EndUpdate() doesn't help.
GeneralRe: Item flickeringmemberPaw Jershauge31 Mar '10 - 11:26 
Then in my experience, you will have to use Native P/invoke to handle treenodes, thats the only way for you to handle large treeviews in an multithreaded envioment. look here for more info : http://msdn.microsoft.com/en-us/library/bb773456(VS.85).aspx[^]
With great code, comes great complexity, so keep it simple stupid...Shucks | :-> Shucks | :->

GeneralRe: Item flickeringmemberSauls1 Apr '10 - 3:18 
I'm new to C# so I really don't know how to insert this structure in the app, could you give me a hand? Smile | :)
GeneralRe: Item flickeringmemberPaw Jershauge1 Apr '10 - 3:30 
Sure mate, ill be happy to give a hand, but can it please wait, till Easter is over Wink | ;) Wink | ;) Wink | ;)
With great code, comes great complexity, so keep it simple stupid...Shucks | :-> Shucks | :->

GeneralRe: Item flickeringmemberSauls1 Apr '10 - 5:39 
ok, thanks. Happy Easter then, later Wink | ;)
GeneralRe: Item flickeringmemberSauls7 Apr '10 - 4:07 
So, can someone help me with the code?
GeneralRe: Item flickeringmemberPaw Jershauge8 Apr '10 - 1:27 
Hey Sauls
 
I dont know why i didnt get the notification about you writing to me here on CP. But yes i will shortly make a demo for you and post it somewhere.
With great code, comes great complexity, so keep it simple stupid...Shucks | :-> Shucks | :->

GeneralRe: Item flickeringmemberSauls8 Apr '10 - 13:21 
ok, thank you very much Wink | ;)
GeneralRe: Item flickeringmemberPaw Jershauge11 Apr '10 - 23:44 
Hey Sauls
 
Im sorry ive been hung up on work, so i havnt had the time to post any exsample for you, have you tried what Tarek Najem has posted ???
With great code, comes great complexity, so keep it simple stupid...Shucks | :-> Shucks | :->

GeneralRe: Item flickeringmemberSauls12 Apr '10 - 6:58 
yea, I've tried, but it didn't helped, maybe I'm doing something wrong, or maybe the code is wrong...
AnswerRe: Item flickeringmemberTarek Najem11 Apr '10 - 2:08 
In class treelistview code that exist in (TreeListView.cs File) view this code and replace your code:
 
        
        #region Constructor
        /// <summary>
        /// Create a new instance of a TreeListView
        /// </summary>
        public TreeListView()
        {
            m_ColumnHeaderTextType = new System.Collections.Generic.Dictionary<ColumnHeader, Type>();
 
            InitializeComponent();
 
            if (!IsHandleCreated)
                CreateHandle();
            _items = new TreeListViewItemCollection(this);
            _items.SortOrder = _sorting;
            _comctl32Version = APIsComctl32.GetMajorVersion();
 
            //int style = APIsUser32.SendMessage(Handle, (int)APIsEnums.ListViewMessages.GETEXTENDEDLISTVIEWSTYLE, 0, 0);
            //style |= (int)(APIsEnums.ListViewExtendedStyles.INFOTIP | APIsEnums.ListViewExtendedStyles.LABELTIP);
            //APIsUser32.SendMessage(Handle, (int)APIsEnums.ListViewMessages.SETEXTENDEDLISTVIEWSTYLE, 0, style);
        }
        #endregion
 
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams CP = base.CreateParams;
                
                CP.ExStyle  |= 
                    (int)
                    (
                            APIsEnums.ListViewExtendedStyles.INFOTIP 
                        |   APIsEnums.ListViewExtendedStyles.LABELTIP
                        |   APIsEnums.ListViewExtendedStyles.DOUBLEBUFFER
                    );
 
                return CP;
            }
        }
 
================== Wannabe from God that this will be what you want ===============
GeneralThanks!memberAlex_hbg3 Mar '10 - 10:36 
Really great work you've done here. Just wanted to say thank you Smile | :)
QuestionIcons in imageList1 cannot be displayedmembervictorguo161325 Feb '10 - 22:15 
The plus/ minus can be displayed.
But the icons in imageList1 cannot.
Why? D'Oh! | :doh:
GeneralCancel Edit label and Drag'N'Dropmembermushik3 Feb '10 - 5:42 
I have an event handler TreeListView_ItemDrag(object sender, ItemDragEventArgs e)
 
When I canceled edit label (by press ESC) TreeListView has rised an ItemDrag event. How can I cancel ItemDrag rising?
Generalhide columnmemberlonguard12 Jan '10 - 4:39 
i seach a way to have a column with visible attribute set to false, anyone know how to do
GeneralRe: hide columnmemberTarek Najem23 Feb '10 - 2:01 
Step 1- Remove Column when you need to visible
Step 1- Readd Column when you need to show
 


m_TreeListView.Columns.Remove(m_ColumnHeader); // to visible
 
// to show
m_ColumnHeader.DisplayIndex = 3;
m_TreeListView.Columns.Add(m_ColumnHeader);
 

AnswerSearch Feature In TreeListViewmemberTarek-Najem9 Nov '09 - 21:27 
Add this code to the TreeListView to add the search feature:
 
        public TreeListViewItem Search(string Criteria, bool IfEndResearchFromBeginning)
        {
            TreeListViewItem TempItem = null;
            if (this.SelectedItems.Count == 0)
            {
                if (this.Items.Count == 0) return null;
 
                TempItem = this.Items[0];
            }
            else
                TempItem = this.SelectedItems[0];
 
            return Search(TempItem, Criteria, IfEndResearchFromBeginning);
        }
 
        public TreeListViewItem Search(TreeListViewItem StartItem, string Criteria, bool IfEndResearchFromBeginning)
        {
            Criteria = Criteria.ToLower();
            bool Research = false;
 
        BEGIN_SEARCH:
 
            if (String.IsNullOrEmpty(Criteria) || StartItem == null) return null;
 
            TreeListViewItem TempItem = SearchChild(Criteria, StartItem.Items);
            if (TempItem != null)
                return TempItem;
 
            TreeListViewItemCollection ItemCollection;
 
        SEARCH_NEXT:
            if (StartItem.Parent == null)
                ItemCollection = _items;
            else
                ItemCollection = StartItem.Parent.Items;
 
            int ItemIndex = ItemCollection.GetIndexOf(StartItem) + 1;
            if (ItemIndex > (ItemCollection.Count - 1))
            {
                if (ItemCollection == _items)
                {
                    if (this.Items.Count > 0 && !Research && IfEndResearchFromBeginning)
                    {
                        Research = true;
                        StartItem = this.Items[0];
                        goto BEGIN_SEARCH;
                    }
                    return null;
                }
 
                StartItem = StartItem.Parent;
                goto SEARCH_NEXT;
            }
 
            StartItem = ItemCollection[ItemIndex];
 
            while (true)
            {
                string ItemText = StartItem.Text.ToLower();
                if (ItemText.IndexOf(Criteria) > -1)
                {
                    return StartItem;
                }
 
               TempItem = SearchChild(Criteria, StartItem.Items);
                if (TempItem != null)
                    return TempItem;
 
                ItemIndex++;
 
                if (ItemIndex > (ItemCollection.Count - 1))
                {
                    if (ItemCollection == _items)
                    {
                        if (this.Items.Count > 0 && !Research && IfEndResearchFromBeginning)
                        {
                            Research = true;
                            StartItem = this.Items[0];
                            goto BEGIN_SEARCH;
                        }
                        return null;
                    }
 
                    StartItem = StartItem.Parent;
                    goto SEARCH_NEXT;
                }
 
                StartItem = ItemCollection[ItemIndex];
            }
 
            return null;
        }
 
        private TreeListViewItem SearchChild(string Criteria, TreeListViewItemCollection ItemsCollection)
        {
            foreach (TreeListViewItem TargetItem in ItemsCollection)
            {
                string ItemText = TargetItem.Text.ToLower();
 
                if (ItemText.IndexOf(Criteria) > -1)
                    return TargetItem;
 
                if (TargetItem.Items.Count > 0)
                {
                    TreeListViewItem TempItem = SearchChild(Criteria, TargetItem.Items);
                    if (TempItem != null)
                        return TempItem;
                }
            }
            return null;
        }
 
To use it :
 
            TreeListViewItem TargetItem = m_TreeListView.Search("Item 1", true);
            if (TargetItem != null)
            {
                TargetItem.Selected = true;
                TreeListViewItem[] ExpandedItems = TargetItem.ParentsInHierarch;
                foreach (TreeListViewItem item in ExpandedItems)
                {
                    item.Expand();
                }
                m_TreeListView.TopItem = TargetItem;
 
                if (FocusTree)
                    m_TreeListView.Focus();
            }

GeneralImage in a SubItemmembertigor14 Sep '09 - 7:04 
Hi,
is it possible to set images in subitems?
GeneralProblem with BeginEditmemberjose.mira8 Jul '09 - 4:24 
Hi. I'm trying to allow the user to navigate from one editable cell to another, having only 2 columns that can be edited.
On the BeforeLabelEdit event I check if the clicked column is one that can be edited.
On de AfterLabelEdit, if the column being edited is the first one I call the BeginEdit method sending the second column's index as parameter, which works fine.
My problem is that once on the second editable column, when pressing Enter nothing happens. I suspect that it has something to do with the _inedit property in TreeListView.cs, which is set to false when the second column is editable.
My code is bellow. Can any one shed some light on this? Thanks.
 
private void tlvA_BeforeLabelEdit(object sender, System.Windows.Forms.TreeListViewBeforeLabelEditEventArgs e)
{
    if(!(e.Item.Parent == null && (e.ColumnIndex == _ColumnQtyF || e.ColumnIndex == _ColumnQtyR)))
    {
        e.Cancel = true;
    }
}
 
private void tlvA_AfterLabelEdit(object sender, System.Windows.Forms.TreeListViewLabelEditEventArgs e)
{
    if(e.ColumnIndex == _ColumnQtyF)
    {
        TreeListViewItem _tlvi = (TreeListViewItem)tlvA.SelectedItems[0];
        if(System.Text.RegularExpressions.Regex.IsMatch(e.Label, @"^(-)?[0-9]+((\.|,)[0-9]+)?$"))
        {
            _tlvi.BeginEdit(_ColumnQtyR);
        }
        else
        {
            e.Cancel = true;
            _tlvi.BeginEdit(_ColumnQtyF);
        }
    }
    else if(e.ColumnIndex == _ColumnQtyR)
    {
        TreeListViewItem _tlvi = (TreeListViewItem)tlvA.SelectedItems[0];
        if(System.Text.RegularExpressions.Regex.IsMatch(e.Label, @"^(-)?[0-9]+((\.|,)[0-9]+)?$"))
        {
            // SQL statements
            // ...
            // Move to next line, if it exists
        }
        else
        {
            e.Cancel = true;
            _tlvi.BeginEdit(_ColumnQtyR);
        }
    }
}

GeneralForeColor of TreeViewItem on Expand wrongmemberWilfriedR15 May '09 - 10:29 
I have a Problem if i have set a color on a TreeNodeItem. If i expand it is that Node, where i ckicked on + in Black ForeColor. All childs are in correct color.
 
how can i fixed it?
General"TreeListView.ExitEdit()" bug fixmemberBuddyLeeJr17 Apr '09 - 7:33 
There are a couple odd things happening in this function, but this was an easy fix that allowed me to get to the actual correct item (note the use of 'editedItem' instead of 'EditedItem' ):
 
if(!Cancel)
{
TreeListViewLabelEditEventArgs e = new TreeListViewLabelEditEventArgs( editedItem.Item, editedItem.ColumnIndex, Text );
e.Cancel = Cancel;
GeneralRe: "TreeListView.ExitEdit()" bug fixmemberhirenkshah19 Apr '09 - 18:19 
Thanks BuddyLeeJr, its done.
Same way i have to call function "exitEdit",
if i want to move selected row up & down (with focused item). call exitedit &
setRange(nextvisibleitem,nextvisibleitem).
 
Thanks
hiren shah

QuestionHow to call begin edit on key press in TreeListView..memberhirenkshah12 Apr '09 - 18:35 
Hello sir,
 
I am using Treelistview C# component in my project,
It is almost finish except (cell)label edit on key press.
 
Below is brief of my code, I can not send code outside from my office otherwise I could have sent you same code, which I had written.
 
I wanted to call “begin edit” event, when keyboard key press like ‘F2’
I have tried to update override function call wndproc() of project TreeListview2002.dll
In the region key-Down “BeginEdit ”,
Checking key code is “F2” then
Wrote same thing which is already there in “Beginlabeledit region under notify region.
Get edit handle can call the same wndproc(reff mess)
 
But it want work, can you help me to complete this.
 
Thanks
hiren shah

AnswerRe: How to call begin edit on key press in TreeListView..memberBuddyLeeJr17 Apr '09 - 7:28 
In TreeListView.cs, add the following code:
public void BeginEdit( )
{
if( base.SelectedItems.Count > 0 )
base.SelectedItems[0].BeginEdit();

}
 
Then in your form code, handle PreviewKeyDown and do something like this:
private void treeListView1_PreviewKeyDown( object sender, PreviewKeyDownEventArgs e )
{
if( e.KeyCode == Keys.F2 )
{
treeListView1.BeginEdit( );
}
}
QuestionKey Navigation - F2 beginEditmemberhirenkshah3 Apr '09 - 22:19 
hi,
i am using treelistview in my project, i am finding way to edit specific column on key press.
like
Pressing F2 enters edit mode or i will call beginEdit event.
i am calling beginEdit event and passing required paramiters, but it is not working.
 
if you know how will i achinve this, please let me know the solution.
 
my email id is hirenkshah@gamil.com.
 
Thanks,
Hiren Shah.
 
Thanks
hiren shah

GeneralNewbie code : TreeList is Win32 native !memberkilt31 Mar '09 - 3:36 
Why re-inventing the wheel with poor code ?!!!
The TreeList control is a native Win32 control !
(pure C /Win32 had been posted on Win32 api group
http://groups.google.com/group/comp.os.ms-windows.programmer.win32/topics[
Generalwhere can i found an update for the treelistview controlmemberron197730 Mar '09 - 5:15 
Hi,
i have several bugs with the control.
vertical scroll bar is not working correctly
some times he client crashes when i am using the control
is there any update for the control??
thanks.
QuestionHow to get to work on x64membermax_slayer30 Mar '09 - 2:01 
In file APIsStructs.cs
Change structure
public struct NMHDR
{
public IntPtr hwndFrom;
public int idFrom;
public int code;
}
 
to
 
public struct NMHDR
{
public IntPtr hwndFrom;
public IntPtr idFrom;
public int code;
}
 
It's all!!!)))
AnswerRe: How to get to work on x64memberJustin Freitas24 Jul '09 - 5:41 
I too had to make this fix to get the plus/minus and expansion lines to display under x64. Thanks for the fix. -Justin
AnswerRe: How to get to work on x64memberPapirov15 Apr '10 - 15:04 
THANK YOU!!!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 1 Sep 2003
Article Copyright 2002 by Thomas Caudal
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid