TreeView and TreeNode

T

Tony

Hello!

I have a TreeView where I have added one TreeNode which is named Country and
below this country node I have added several TreeNode which are different
countries such as Sweden, Norway ,Polen and so on.

I have also a ContextMenuStrip with one item added which is Statistics.
So when I right click on for example Sweden or Norway or Polen the context
meny with Statictics is displayed so this works good.
In method AddCountries below I have added this row
node.ContextMenuStrip = textBoxMenu;

Now to my problem when I right click on any county(Sweden, Norway ,Polen )
and then choose Statistics I must
be able to find which country I have clicked on. I have made an attempt to
solve this in method textBoxMenu_Opening and method
GetStatisticContext_Click.
In method textBoxMenu_Opening I have hoped by using SourceControl in this
way
this.Tag = ((ContextMenuStrip)sender).SourceControl;
to be able to get the TreeNode I clicked on and save it in the Tag for the
form.

So when I click on Statistics eventHandler GetStatisticContext_Click is
called
and here I have hoped by using the result in Tag to know which TreeNode I
have clicked on.

This doesn's work so I hope that somebody can make any suggestion where to
change so I can get it
to work.


public partial class TimeFlowMDIForm : Form
{
....
public TimeFlowMDIForm() : base()
{
InitializeComponent();
treeView.Nodes.Add(CreateCountryView());
}

private TreeNode CreateCountryView()
{
TreeNode Country = new TreeNode();
Country.Name = "Country";
Country.Text = "Country";
AddCountries(ref Country);
return Country;
}

private void AddCountries(ref TreeNode parent)
{
ds = DA.GetAllRowsForTable(connectionString, "Country");

if (Primer.Common.Data.DataSet.HasData(ds))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
TreeNode node = new TreeNode();
node.ContextMenuStrip = textBoxMenu;
node.Name = row["CountryId"].ToString();
node.Text = row["Name"].ToString();
parent.Nodes.Add(node);
}
}
}

private void textBoxMenu_Opening(object sender, CancelEventArgs e)
{
this.Tag = ((ContextMenuStrip)sender).SourceControl;
}

private void GetStatisticContext_Click(object sender, EventArgs e)
{
Type slask2 = sender.GetType();
string slask = this.Tag.ToString();
}


//Tony
 
M

Morten Wennevik [C# MVP]

Hi Tony,

A TreeNode is not a Control so it will therefore not show up as
SourceControl. Instead the Control containing the TreeNode is used.

I think you will have to handle the TreeView.NodeMouseClicked and temporary
store the clicked node.

TreeNode menuNode = null;
void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
if (e.Node.Parent != null && e.Button == MouseButtons.Right)
menuNode = e.Node;
else
menuNode = null;
}

--
Happy Coding!
Morten Wennevik [C# MVP]


Tony said:
Hello!

I have a TreeView where I have added one TreeNode which is named Country and
below this country node I have added several TreeNode which are different
countries such as Sweden, Norway ,Polen and so on.

I have also a ContextMenuStrip with one item added which is Statistics.
So when I right click on for example Sweden or Norway or Polen the context
meny with Statictics is displayed so this works good.
In method AddCountries below I have added this row
node.ContextMenuStrip = textBoxMenu;

Now to my problem when I right click on any county(Sweden, Norway ,Polen )
and then choose Statistics I must
be able to find which country I have clicked on. I have made an attempt to
solve this in method textBoxMenu_Opening and method
GetStatisticContext_Click.
In method textBoxMenu_Opening I have hoped by using SourceControl in this
way
this.Tag = ((ContextMenuStrip)sender).SourceControl;
to be able to get the TreeNode I clicked on and save it in the Tag for the
form.

So when I click on Statistics eventHandler GetStatisticContext_Click is
called
and here I have hoped by using the result in Tag to know which TreeNode I
have clicked on.

This doesn's work so I hope that somebody can make any suggestion where to
change so I can get it
to work.


public partial class TimeFlowMDIForm : Form
{
....
public TimeFlowMDIForm() : base()
{
InitializeComponent();
treeView.Nodes.Add(CreateCountryView());
}

private TreeNode CreateCountryView()
{
TreeNode Country = new TreeNode();
Country.Name = "Country";
Country.Text = "Country";
AddCountries(ref Country);
return Country;
}

private void AddCountries(ref TreeNode parent)
{
ds = DA.GetAllRowsForTable(connectionString, "Country");

if (Primer.Common.Data.DataSet.HasData(ds))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
TreeNode node = new TreeNode();
node.ContextMenuStrip = textBoxMenu;
node.Name = row["CountryId"].ToString();
node.Text = row["Name"].ToString();
parent.Nodes.Add(node);
}
}
}

private void textBoxMenu_Opening(object sender, CancelEventArgs e)
{
this.Tag = ((ContextMenuStrip)sender).SourceControl;
}

private void GetStatisticContext_Click(object sender, EventArgs e)
{
Type slask2 = sender.GetType();
string slask = this.Tag.ToString();
}


//Tony
 
S

sloan

Here is some code to help you with a "1 hit" to the database.
You can populate NodeDS however you wish (usp, or manually).
But once its populated (as an entirity)....you don't need to rehit the
database.





Create a Strong DataSet. Name it "NodeDS".
Add a table called "NodeInfo"

Add these columns.

NodeUUID (Guid)
NodeName (string)
NodeAbbreviationName (string)
NodeParentUUID (Guid)
StaticNestLevel (int32)


NOW, the most important part. Build a relationship between NodeParentUUID
that references back to NodeUUID.
NAME the relationship "NodeInfo_NodeInfo".


If you do that and then populate the dataset with data like this:



NodeUUID NodeName
NodeAbbreviationName NodeParentUUID
StaticNestLevel
------------------------------------ ----------------------------------------------------------------
-------------------------------- ------------------------------------ ---------------


AAA00000-0000-0000-0000-000000000001 , Countries , Countries ,
00000000-0000-0000-0000-000000000000 1
BBB00000-0000-0000-0000-000000000001 , United States , USA ,
AAA00000-0000-0000-0000-000000000001 , 2
BBB00000-0000-0000-0000-000000000002 , Mexico , MEX ,
AAA00000-0000-0000-0000-000000000001 , 2
BBB00000-0000-0000-0000-000000000003 , Canada , CAN ,
AAA00000-0000-0000-0000-000000000001 , 2



The code to populate will be something like this:

NodeDS myDS = new NodeDS();
myDS.NodeInfo.AddNewNodeInfoRow ( "AAA00000-0000-0000-0000-000000000001" ,
"Countries" , "Countries" , "00000000-0000-0000-0000-000000000000" , 1 );
//add more rows as described above, I'll leave that to you


//report the success
Console.Writeline ( ds.GetXml() ) ;





Then implement this code:


public static TreeView GrowTreeView(TreeView srcTreeView, string[]
friendlyValueText, string friendlyValueDelim, string[] idValues, string
idDelimiter, DataRow[] rowResults, TreeNode parentNode, string
childRelationName)
{


TreeNode nodeCurrentLevelToAdd;
bool rootNodeExistsCheck = true;

int i = 0;// 'loop for the array args
try
{
//'this Try/Catch makes sure a root node exists, if not, there is
logic to create one
TreeNode rootNodeCheck = new TreeNode();
rootNodeCheck = (srcTreeView.Nodes[0]);
rootNodeExistsCheck = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
rootNodeExistsCheck = false;
}

if (rootNodeExistsCheck == false)
{
if (parentNode == null)
{
//'in case the parentNode isn't defined (at the root level)
//'this will create a default rootNode
parentNode = new TreeNode("--Expand--");// 'set your own default
values here for the root node
parentNode.Tag = "0";// 'set your own default values here for the
root node
}

srcTreeView.Nodes.Add(parentNode);//

//'note about this IF loop, it should only ever be executed
//'on the "first" call, the recursive calls should never get here
}


foreach (DataRow parentrow in rowResults)
{

//'this is the friendly value
//'notice you can use a "compound" friendly value because of the
array string as a parameter
string friendlyValue = "";//

for (i = 0; i <= friendlyValueText.Length - 1; i++)
{

friendlyValue += parentrow[friendlyValueText];//
if (i != (friendlyValueText.Length - 1) &&
(friendlyValueText.Length > 0))
{
friendlyValue += friendlyValueDelim;//
}
}
nodeCurrentLevelToAdd = new TreeNode(friendlyValue);//


//'this is the "ID" value (the "not seen" value)
//'this can also be a "compound" value, but most times it won//'t
//'be, it will be the unique identifier on the row
string idValue = "";//

for (i = 0; i <= idValues.Length - 1; i++)
{
idValue += Convert.ToString(parentrow[idValues]);//
if (i != (idValues.Length - 1) && (idValues.Length > 0))
{
idValue += idDelimiter;//
}
}
nodeCurrentLevelToAdd.Tag = idValue;//

//'the node to add has been defined, now add this node to its parent
node
parentNode.Nodes.Add(nodeCurrentLevelToAdd);//

//'//'//'//'populate child//'//'//'//'//'

TreeNode childnode;//
childnode = new TreeNode();//

DataRow[] childRows;//
childRows = parentrow.GetChildRows(childRelationName);//

//'here is the recursive call
GrowTreeView(srcTreeView, friendlyValueText, friendlyValueDelim,
idValues, idDelimiter, childRows, nodeCurrentLevelToAdd,
childRelationName);//

}//Next parentrow;//

return srcTreeView;
}







THEN call it like this: (you will draw a TreeView called tvNodes onto your
winforms screen)



NodeDS myDS = new NodeDS();
//populate it as I describe above.




TreeNode rootTreeNode = null;
//the next 2 lines are OPTIONAL, comment them (next 4 lines) out and
see what happens
rootTreeNode = new TreeNode();
rootTreeNode = new TreeNode("--Select--");
string[] friendlyNameDataCols = { "NodeName", "NodeAbbreviation",
"StaticNestLevel" };
string[] idValueDataCols = { "NodeUUID" };


this.tvNodes.Nodes.Clear();

this.tvNodes = MyClass.GrowTreeView(this.tvNodes,
friendlyNameDataCols, " , ", idValueDataCols, ":",
myDS.NodeInfo.Select("StaticNestLevel=1"), rootTreeNode,
"NodeInfo_NodeInfo");








Tony said:
Hello!

I have a TreeView where I have added one TreeNode which is named Country
and
below this country node I have added several TreeNode which are different
countries such as Sweden, Norway ,Polen and so on.

I have also a ContextMenuStrip with one item added which is Statistics.
So when I right click on for example Sweden or Norway or Polen the context
meny with Statictics is displayed so this works good.
In method AddCountries below I have added this row
node.ContextMenuStrip = textBoxMenu;

Now to my problem when I right click on any county(Sweden, Norway ,Polen )
and then choose Statistics I must
be able to find which country I have clicked on. I have made an attempt to
solve this in method textBoxMenu_Opening and method
GetStatisticContext_Click.
In method textBoxMenu_Opening I have hoped by using SourceControl in this
way
this.Tag = ((ContextMenuStrip)sender).SourceControl;
to be able to get the TreeNode I clicked on and save it in the Tag for the
form.

So when I click on Statistics eventHandler GetStatisticContext_Click is
called
and here I have hoped by using the result in Tag to know which TreeNode I
have clicked on.

This doesn's work so I hope that somebody can make any suggestion where to
change so I can get it
to work.


public partial class TimeFlowMDIForm : Form
{
...
public TimeFlowMDIForm() : base()
{
InitializeComponent();
treeView.Nodes.Add(CreateCountryView());
}

private TreeNode CreateCountryView()
{
TreeNode Country = new TreeNode();
Country.Name = "Country";
Country.Text = "Country";
AddCountries(ref Country);
return Country;
}

private void AddCountries(ref TreeNode parent)
{
ds = DA.GetAllRowsForTable(connectionString, "Country");

if (Primer.Common.Data.DataSet.HasData(ds))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
TreeNode node = new TreeNode();
node.ContextMenuStrip = textBoxMenu;
node.Name = row["CountryId"].ToString();
node.Text = row["Name"].ToString();
parent.Nodes.Add(node);
}
}
}

private void textBoxMenu_Opening(object sender, CancelEventArgs e)
{
this.Tag = ((ContextMenuStrip)sender).SourceControl;
}

private void GetStatisticContext_Click(object sender, EventArgs e)
{
Type slask2 = sender.GetType();
string slask = this.Tag.ToString();
}


//Tony
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top