Recently I needed to implement multiselect tree view. Knowing that there is nothing new under the sun I googled for solution and found this article. At first glance it worked as expected, however later I had to improve it.
- it does not support editing of text nodes;
- added property for turning off multiselect;
- removed built-in tooltips;
- enabled node selection with clicks in a row, not only on text and icon.
// Disable built-in tooltips
protected override CreateParams CreateParams
{
get
{
CreateParams parms = base.CreateParams;
parms.Style |= 0x80; // Turn on TVS_NOTOOLTIPS
return parms;
}
}
// Switch to enable or disable multiselect
private bool _multiSelectEnabled;
public bool MultiSelectEnabled
{
get { return _multiSelectEnabled; }
set
{
_multiSelectEnabled = value;
//reset selection
if (!_multiSelectEnabled && SelectedNodes.Count > 0)
SelectedNode = SelectedNodes[0];
}
}
private List m_SelectedNodes;
public List SelectedNodes
{
get { return m_SelectedNodes; }
set
{
ClearSelectedNodes();
if (MultiSelectEnabled)
{
if (value != null)
{
foreach (TreeNode node in value)
{
ToggleNode(node, true);
}
}
}
else
{
if (value.Count > 0)
{
m_SelectedNodes.Clear();
ToggleNode(value[0], true);
}
}
}
}
// if user clicks on node, we will check if we need to edit nodes text
private TreeNode _clickedNode;
protected override void OnMouseDown(MouseEventArgs e)
{
// If the user clicks on a node that was not previously selected, select it now.
try
{
base.SelectedNode = null;
TreeNode node = this.GetNodeAt(e.Location);
if (node != null)
{
if (ModifierKeys == Keys.None && (m_SelectedNodes.Contains(node)))
{
_clickedNode = node;
}
else
{
if (MultiSelectEnabled) //if multiselect enabled - SelectNode
{
SelectNode(node);
}
else //else select single node
{
SelectSingleNode(node);
}
}
}
base.OnMouseDown(e);
}
catch (Exception ex)
{
HandleException(ex);
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
try
{
var node = this.GetNodeAt(e.Location);
if (node != null &&
ModifierKeys == Keys.None && m_SelectedNodes.Contains(node))
{
if (MultiSelectEnabled)
{
SelectNode(node);
}
else
{
SelectSingleNode(node);
}
int leftBound = node.Bounds.X;
int rightBound = node.Bounds.Right;
if (_clickedNode == node && e.Location.X > leftBound && e.Location.X < rightBound)
{
_clickedNode.BeginEdit(); // single click on node - we can rename it
}
}
_clickedNode = null; //clear clicked node
base.OnMouseUp(e);
}
catch (Exception ex)
{
HandleException(ex);
}
}
No comments:
Post a Comment