C# TreeView, event when childnode is selected - c#

I have a question concerning TreeViews and their Nodes in C#.
What I currently try to do. I have a TreeView and next to it a TableLayoutPanel. When I click of the Nodes, I want to call a specific Method and display the Data
in the TableLayoutPanel. Displaying the data works fine, but my problem is that I dont know exactly how to determine what Node/ChildNode has been selected.
I have a TreeView that looks like this
Root1
R1Child1
R1Child2
Root2
R2Child1
R2Child2
Root3
R3Child1
R3Child2
I currently handle this by an AfterSelect Method and just check the selected Node for the Text.
private void treeHardware_AfterSelect(object sender, TreeViewEventArgs e)
{
if (e.Node.Text == SysInfo.CPU.Name)
{
deleteRows();
initFixedRows();
updateTableCPU();
}
else if (e.Node.Text == ramNameIdent)
{
deleteRows();
initFixedRows();
updateTableRAM(e.Node.Index);
}
else if (e.Node.Text == "Memory")
{
deleteRows();
initFixedRows();
loadRAMDetails(0);
loadRAMOverview();
}
else if( e.Node.Text == "Mainboard")
{
deleteRows();
initFixedRows();
updateTableMainboard();
}
else
{
Console.WriteLine("ERROR");
}
}
In my Opinion this is a very unpractical way to check what Node has been clicked, because it just checks Strings, and it isnt very effective..
Next Problem, for Memory Node. I display all installed Physical Memories and add each of them as a ChildNode. Now when I click one of them, it should display the Data of the selected Memory in my TableLayoutPanel. But It always just shows the "last" one.
Hope hat you understand what I mean...
If not, just ask for more Information :-)
Cheers,
Consti

Use the Tag Property , put an ID in the tag property that is unique for every node

Related

How to retrieve each item in a ListBox C#

I am new to C#, although I did take a quarter of Java last year. I have an assignment due tomorrow, so here is my question. I made a sample little program just so I can hopefully get what I'm looking for. I am wondering, how the heck do I look at the listBox and say, for example, if the item soccer is selected, do one thing, but if anything else is selected, do another thing? I will upload a piece of code that doesn't do what its supposed to do, and you all can call me stupid, and then give me the answer.
private void submitButton_Click(object sender, EventArgs e)
{
string best;
best = namesListBox.SelectedItem.ToString();
if ((string)namesListBox.SelectedItem == "Soccer")
{
MessageBox.Show("Fried chicken, don't let that bird die in vain.");
}
else
{
MessageBox.Show("Long long ago, in the land of the Hobbit...");
}
}
private void exitButton_Click(object sender, EventArgs e)
{
Close();
}
}
}
Every time this code runs, I always get Long, long ago.... That is not what I want to see. Any help would be appreciated, I'm about to give up on this program. This is not the actual program, that one is alot more complicated, I just made this one to demonstrate my question... Thanks in advance
Yuriy,
It looks like you are casing the selected item to a string. I have a feeling this may be the problem.
What exactly are you using the string 'best' for? you defined it, but it is not used in your example.
Is this what you are looking for? Try using the ToString() method, and trim it so that whitespace will not throw your code off:
string selectedItem = namesListBox.SelectedItem.ToString().Trim();
if (selectedItem == "Soccer")
MessageBox.Show("Soccer is selected.");
else
MessageBox.Show("NOT SELECTED");
Maybe it is a casing error? If you don't want to worry about uppercase or lowercase, try appending .ToLower() to your string:
string selectedItem = namesListBox.SelectedItem.ToString().Trim().ToLower();
if (selectedItem == "Soccer".ToLower())
// Handle code accordingly.
else
// Handle accordingly.
You can also search your ListBox for a string and find out where it is. Then determine whether the user has selected that particular item:
int selIndex = namesListBox.FindString("Soccer");
This will return a zero-based index of the location of the first item containing the word "Soccer" in it.
Now handle the selected index:
if (namesListBox.SelectedIndex != -1 &&
namesListBox.SelectedIndex == selIndex)
MessageBox.Show("First item containing \"Soccer\" is selected.");
else
MessageBox.Show("First item containing \"Soccer\" is not selected.");
It is also quite possible that you are using a ListView object rather than an actual ListBox. If this is the case, you will have to take a different approach. This example still uses your ListBox name:
// This assumes that you cannot select multiple items, and that you
// only have one column in your ListView.
string selectedItem = namesListBox.SelectedItems[0].SubItems[0].Text;
if (selectedItem.Trim() == "Soccer") // Continue as before...
Does this work with your project?
EDIT:
Wait. Are you trying to change the selected item to "best" before evaluating?
If so, do it like this:
int selIndex = namesListBox.SelectedIndex;
namesListBox.Items.RemoveAt(selIndex);
namesListBox.Items.Insert(selIndex, "best");
EDIT:
Be sure to include code that handles no selection:
// Will not execute block of code if nothing is selected.
if (namesListBox.SelectedIndex == -1)
{
MessageBox.Show("No item is selected.");
return;
}
I am assuming you are using WPF, and you are using ListBox like this :
<ListBox x:Name="lstGames">
<ListBoxItem Content="Soccor"/>
<ListBoxItem Content="Cricket"/>
</ListBox>
Replace this best = namesListBox.SelectedItem.ToString(); with
best = ((ListBoxItem)namesListBox.SelectedItem).Content.ToString();
and accordingly others too.
Because if you are using itemssource property of ListBox and binding say list of only strings, then your present code will work for you surely, if you have checked UpperCase/LowerCase.
If you are using some item like a Game object with multiple properties then your code won't work and more can be said if you tell how you are binding your listbox to a collection object.
The only thing I was looking for was how to write an if statement and this part of the code you wrote worked perfectly. I guess I had whitespace throwing it off, or I was just overthinking it. But anyhow, my issue is resolved. Thank you very much.
string selectedItem = namesListBox.SelectedItem.ToString().Trim();
if (selectedItem == "Soccer")
MessageBox.Show("Soccer is selected.");
else
MessageBox.Show("NOT SELECTED");

Find controls in listview item template of the same type

I am working on claim expenses application for the staff where I work. Part of the process contains a listview, part of a new requirement is that if an expense type is mileage the user will not be able to edit the item, only delete and resubmit as part of business rules and UK tax reasons etc.
Anyway, I want to be able to find a control in each item of the listview that has a certain text value.
I thought something like the following but this is not correct and I know why.
Label ExpenseTypeLabel = (Label)Expenses.FindControl("ExpenseTypeLabel");
string ExpenseType = (ExpenseTypeLabel.Text.ToString());
if (ExpenseType == "Mileage")
{
foreach (ListViewDataItem thisItem in Expenses.Items)
{
ImageButton btnEdit = (ImageButton)thisItem.FindControl("btnEdit");
btnEdit.Enabled = false;
}
}
The expenses are based on weekending and as the page loads it throws my excepion as It cannot bind to a particular individual control as there are many ExpenseTypeLabels associated with the expense for the current weekending (which loads first).
What I am trying to accomplish here is to find all ExpenseTypeLabels in both the item template and the alternating item template and disable the edit function of that expense item. FYI incase you're wondering the weekending is the expense, and the children are the individual expense items.
Could one of you lovely people please educate me on the best way to accomplish this?
Thanks
Matt
Binding order, and timing for accessing bound items, is extremely important; this is especially true when you have sub controls that have binding items also.
If you want to affect the the display for these bound controls, you can usually do it from the aspx end.
Create a link from the front end to a function on the server end, then pass it all the necessary parameters:
<asp:listview id='lstExpense'>
...
<asp:button id='btnEdit' enabled='<%#= isEnabled(((Expense)Container.DataItem).ExpenseType) %>' ...
...
<asp:listview>
On the server end, make a public function to return that value:
public boolean IsEnabled(string ExpenseType) {
return ('Mileage' != ExpenseType);
}
Best solution though, is to use jQuery. Not exaggerating, but you can accomplish all of that with something as simple as:
$('.rowClass').each(function() {
if ($(this).find('.expenseTypeClass').val() == 'Mileage'))
$(this).find('.btnEditClass').attr('disabled','disabled');
})
use OnItemDataBound event as follows
OnItemDataBound="Expenses_ItemDataBound"
protected void Expenses_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
Label ExpenseTypeLabel = (Label)e.Item.FindControl("ExpenseTypeLabel");
string ExpenseType = (ExpenseTypeLabel.Text.ToString());
if (ExpenseType == "Mileage")
{
// disable button
}
}
}

How to disable a checkbox in a checkedlistbox?

I have some items in a CheckedListBox, I want to disable the CheckBox of first item in it.
i.e. I want to disable the first item in the CheckedListBox, because I want to tell the user visually that option is not available.
Combining 2 of the above partial answers worked great for me.
Add your items to the list with:
myCheckedListBox.Items.Add(myItem, myState);
Where myState is CheckState.Indeterminate for items that should be disabled.
Then add an event handler to keep those items from being changed:
myCheckedListBox.ItemCheck += (s, e) => { if (e.CurrentValue == CheckState.Indeterminate) e.NewValue = CheckState.Indeterminate; };
This does not allow you to use 'Indeterminate' in this list for its normal purpose but it does give a look very similar to what one would expect for a disabled item and it provides the correct behavior!
Though this post is pretty old, the last added answer has been submitted in April this year,
and I hope this will help someone.
I was after something similar : a checked list box that behaves like
a lot of installers, which offer a list of options where some features are required and
thus are both checked and disabled.
Thanks to this post (Can I use a DrawItem event handler with a CheckedListBox?)
I managed to do that, subclassing a CheckedListBox control.
As the OP in the linked post states, in the CheckedListBox control the OnDrawItem event is never fired,
so subclassing is necessary.
It's very basic, but it works.
This is what it looks like (the CheckBox above is for comparison) :
NOTE: the disabled item is really disabled : clicking on it has no effects whatsoever (as far as I can tell).
And this is the code :
public class CheckedListBoxDisabledItems : CheckedListBox {
private List<string> _checkedAndDisabledItems = new List<string>();
private List<int> _checkedAndDisabledIndexes = new List<int>();
public void CheckAndDisable(string item) {
_checkedAndDisabledItems.Add(item);
this.Refresh();
}
public void CheckAndDisable(int index) {
_checkedAndDisabledIndexes.Add(index);
this.Refresh();
}
protected override void OnDrawItem(DrawItemEventArgs e) {
string s = Items[e.Index].ToString();
if (_checkedAndDisabledItems.Contains(s) || _checkedAndDisabledIndexes.Contains(e.Index)) {
System.Windows.Forms.VisualStyles.CheckBoxState state = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedDisabled;
Size glyphSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, state);
CheckBoxRenderer.DrawCheckBox(
e.Graphics,
new Point(e.Bounds.X + 1, e.Bounds.Y + 1), // add one pixel to align the check gliph properly
new Rectangle(
new Point(e.Bounds.X + glyphSize.Width + 3, e.Bounds.Y), // add three pixels to align text properly
new Size(e.Bounds.Width - glyphSize.Width, e.Bounds.Height)),
s,
this.Font,
TextFormatFlags.Left, // text is centered by default
false,
state);
}
else {
base.OnDrawItem(e);
}
}
public void ClearDisabledItems() {
_checkedAndDisabledIndexes.Clear();
_checkedAndDisabledItems.Clear();
this.Refresh();
}
}
Use it like this:
checkedListBox.Items.Add("Larry");
checkedListBox.Items.Add("Curly");
checkedListBox.Items.Add("Moe");
// these lines are equivalent
checkedListBox.CheckAndDisable("Larry");
checkedListBox.CheckAndDisable(0);
Hope this can help someone.
Disabling items isn't a great idea, the user will have no good feedback that click the check box won't have any effect. You cannot use custom drawing to make it obvious. Best thing to do is to simply omit the item.
You can however easily defeat the user with the ItemCheck event:
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
if (e.Index == 0) e.NewValue = e.CurrentValue;
}
To disable any particular item use following:
checkedListBox1.SetItemCheckState(0, CheckState.Indeterminate);
SetItemCheckState takes index of item and CheckState Enum
Indeterminate is used to show shaded appearance
I know it has been a while, but I found this in my search for a list box and thought I would add it to the discussion.
If you have a listbox and want to disable all of the checkboxes so they cannot be clicked, but not disable the control so the user can still scroll etc. you can do this:
listbox.SelectionMode = SelectionMode.None
The CheckedListBox will not work in this way. CheckedListBox.Items is a collection of strings so they cannot be "disabled" as such.
Here are some discussions about possible solutions that might help you: here and here.
This works for me:
checkedListBox1.SelectionMode = SelectionMode.None;
Which means no items can be selected
None: No items can be selected.
For more info, you can check it here: SelectionMode Enumeration.
The solution is to use the event ItemChecking:
_myCheckedListBox.ItemChecking += (s, e) => e.Cancel = true;
This will cancel all the checking on every item, but you can always do more refined solution but testing the current .SelectedItem
Here's how I did it in a helpdesk application I wrote:
First, I made it so the check box was greyed out as I added it to the list during form load:
private void frmMain_Load(object sender, EventArgs e)
{
List<string> grpList = new List<string>();
ADSI objADSI = new ADSI();
grpList = objADSI.fetchGroups();
foreach (string group in grpList)
{
if (group == "SpecificGroupName")
{
chkLst.Items.Add(group, CheckState.Indeterminate);
}
else
{
chkLst.Items.Add(group);
}
}
Then I used an event so that when clicked it ensures it stays clicked:
private void chkLst_SelectedIndexChanged(object sender, EventArgs e)
{
if (chkLst.SelectedItem.ToString() == "SpecificGroupName")
{
chkLst.SetItemCheckState(chkLst.SelectedIndex, CheckState.Indeterminate);
}
}
The idea here is that on my form it's set so that the box checks on item click/select. This way I could kill two birds with one stone. I could keep this event from causing problems when the item is first checked and added during form load. Plus making it check on select allows me to use this event instead of the item checked event. Ultimately the idea is to keep it from messing up during the load.
You'll also notice that it doesn't matter what the index number is, that variable is unknown because in my app it's grabbing a list of groups from AD that exist in a specific OU.
As to whether this is a good idea or not, that's dependent on the situation. I have another app where the item to disable is dependent on another setting. In this app I just want the helpdesk to see that this group is required so they don't go removing them from it.
Try Below Code:
Private Sub CheckedListBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles CheckedListBox1.MouseUp
If (Condition) Then
Me.CheckedListBox1.SelectedIndex = -1
End If
End Sub
I think an alternative solution, is using Telerik components.
A RadListControl can give you that option:

WPF: How to walk up the Visual Tree to find a Model3DGroup a clicked 3d-model is in?

I'm displaying a few 3D-models as Model3DGroups.
They are surrounded by Viewport3D which catches MouseDown-events.
I want to determine which Model3DGroup (they all have names) was clicked.
I'm starting with this:
Point location = e.GetPosition(karte.ZAM3DViewport3D);
HitTestResult hitResult = VisualTreeHelper.HitTest(karte.ZAM3DViewport3D, location);
if (hitResult != null )
{
Debug.WriteLine("BREAKPOINT");
// Hit the visual.
}
After hitting the breakpoint set at the WriteLine-command I'm looking at the local-view to find the right variable but can't find it.
Can you help me out which path I need to take to find the group, the modelvisual3d belongs to?
Here is a screenshot of the tree:
I did it by surrounding the Model3DGroup with a ModelUIElement3D.
<ModelUIElement3D MouseDown="ModelUIElement3D_MouseDown" x:Name="LogoMouseDown">
the MouseDown-function handles it this way:
private void ModelUIElement3D_MouseDown(object sender, MouseButtonEventArgs e)
{
if (sender == trololo)
{
RaiseModelClickEvent("auditorium");
}
else if (sender == LogoMouseDown)
{
RaiseModelClickEvent("logo");
}
}
You could use Linq to Visual Tree as it doesn't matter whether the named element you are looking for is Model3DGroup. It is just another Dependency Object (if I understand your question).
Check result's type and then LinqToVT to go up, retrieving it's XAML predecessor:
hitResult.VisualHit.GetType() == typeof(ModelVisual3D)

Tooltips for CheckedListBox items?

Is there a straighforward way to set additional text to appear in a tooltip when a user's mouse is held over an item in a CheckedListBox?
What I would expect to be able to do in code is:
uiChkLstTables.DisplayOnHoverMember = "DisplayOnHoverProperty"; //Property contains extended details
Can anyone point me in the right direction to do this? I've already found a couple of articles that involve detecting which item the mouse is currently over and creating a new tooltip instance, but this sounds a little too contrived to be the best way.
Thanks in advance.
Add a Tooltip object to your form and then add an event handler for the CheckedListBox.MouseHover that calls a method ShowToolTip();
Add MouseMove event of your CheckedListBox which has the following code:
//Make ttIndex a global integer variable to store index of item currently showing tooltip.
//Check if current location is different from item having tooltip, if so call method
if (ttIndex != checkedListBox1.IndexFromPoint(e.Location))
ShowToolTip();
Then create the ShowToolTip method:
private void ShowToolTip()
{
ttIndex = checkedListBox1.IndexFromPoint(checkedListBox1.PointToClient(MousePosition));
if (ttIndex > -1)
{
Point p = PointToClient(MousePosition);
toolTip1.ToolTipTitle = "Tooltip Title";
toolTip1.SetToolTip(checkedListBox1, checkedListBox1.Items[ttIndex].ToString());
}
}
Alternately, you could use a ListView with checkboxes instead. This control has
builtin support for tooltips.
Contrived or not; that's what there is...
I'm not aware of an easier way than you have already described (although I'd probably re-use a tooltip instance, rather than creating new all the time). If you have articles that show this, then use them - or use a 3rd party control that supports this natively (none leap to mind).
I would like to expand upon Fermin's answer in order to perhaps make his wonderful solution slightly more clear.
In the form that you're working in (likely in the .Designer.cs file), you need to add a MouseMove event handler to your CheckedListBox (Fermin originally suggested a MouseHover event handler, but this did not work for me).
this.checkedListBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.showCheckBoxToolTip);
Next, add two class attributes to your form, a ToolTip object and an integer to keep track of the last checkbox whose tool tip was shown
private ToolTip toolTip1;
private int toolTipIndex;
Finally, you need to implement the showCheckBoxToolTip() method. This method is very similar to Fermin's answer, except that I combined the event callback method with the ShowToolTip() method. Also, notice that one of the method parameters is a MouseEventArgs. This is because the MouseMove attribute requires a MouseEventHandler, which then supplies MouseEventArgs.
private void showCheckBoxToolTip(object sender, MouseEventArgs e)
{
if (toolTipIndex != this.checkedListBox.IndexFromPoint(e.Location))
{
toolTipIndex = checkedListBox.IndexFromPoint(checkedListBox.PointToClient(MousePosition));
if (toolTipIndex > -1)
{
toolTip1.SetToolTip(checkedListBox, checkedListBox.Items[toolTipIndex].ToString());
}
}
}
Run through your ListItems in your checkbox list of items and set the appropriate text as the item 'title' attribute, and it will display on hover...
foreach (ListItem item in checkBoxList.Items)
{
//Find your item here...maybe a switch statement or
//a bunch of if()'s
if(item.Value.ToString() == "item 1")
{
item.Attributes["title"] = "This tooltip will display when I hover over item 1 now, thats it!!!";
}
if(item.Value.ToString() == "item 2")
{
item.Attributes["title"] = "This tooltip will display when I hover over item 2 now, thats it!!!";
}
}

Categories