i have a little Problem with my treeview.
Background: I have a treeview with multiple Items in it, whenever you click on a Parent or first child an Event should fire where a new window opens where you can do some stuff.
I am using the "After_Select" event of the tree view as following:
if (_inside) //this boolean was my first attempt to deal with the problem
{
if (treeView1.SelectedNode.Parent != null)
{
if (treeView1.SelectedNode.Parent.Parent != null)
{
//its 2nd child -> do nothing
}
else
{
Configuration_New_Click(treeView1.SelectedNode.Parent.Name.ToString(), treeView1.SelectedNode.Name.ToString()); //its 1st child do something
}
}
else
{
Configuration_New_Click(treeView1.SelectedNode.Name.ToString(), ""); //its parent, do something else
}
}
The Problem: The Event fires everytime i for example tab out of the program and tab back in -> the first item in the treeview gets selected -> AfterSelect fires. I have some more situations like this, basically the event does what it should, it fires whenever an item was selected. The problem is the first treeview item gets selected whenever the treeview looses focus by switching windows for example. (it only fires if i clicked a other treeview item than the first before doing so)
I read a bit in the forum and found a solution i tried -> set a boolean to false whenever it should not trigger. it works with some Problems but the event still triggers when i alt+tab to other windows and alt tab back to back programm. is there any quick and dirty solution to handle this?
Thanks for your time and effort!
Edit: Is the "MouseDown" a better solution? and if so, how can i use this event with my code? since i need the selectedNode in order to run the code above?
Regards,
Christian
Related
I am trying to create a reusable Settings dialog and I want to bind the controls in the dialog to the Properties.Settings built into Visual Studio.
This is the code I use to bind each control as I iterate through them:
Control.DataBindings.Add(new Binding(strProperty, Properties.Settings.Default, Control.Name, false, DataSourceUpdateMode.Never));
Where strProperty is resolved to the appropriate Property of the control to bind with. Note the update mode: DataSourceUpdateMode.Never. More on that in a minute.
This code works to bind the control to the setting. When the dialog opens, all the controls display the appropriate values. The problem is with getting the DataSource, i.e. the Properties.Settings, to update properly, and at the right time. When the DataSourceUpdateMode is set to "OnPropertyChanged", it works as expected to update the values, but this isn't the desired behavior of a dialog. You don't want to update until the OK button is pressed, not as soon as the value in the control has changed.
After reading all the documentation I could find, it seemed to me that the best way would be set the DataSourceUpdateMode to "Never" and then when the OK button is pressed I would iterate through all of the controls and call Control.DataBinding[0].WriteValue() to manually update all the properties. But when I did that I found that after the first control was updated, every single one of the remaining controls would immediately revert to it's previous value!
public void UpdateDataSource(Control.ControlCollection ctrls)
{
foreach (Control ctrl in ctrls)
{
if (ctrl.Controls.Count > 0)
{
UpdateDataSource(ctrl.Controls);
}
if (ctrl.DataBindings != null)
{
foreach (Binding binding in ctrl.DataBindings)
{
binding.WriteValue();
}
}
}
}
I also tried something using the DataSourceUpdateMode.OnValidation flag. I set every control's CausesValidation property to false to prevent updates from occurring before the OK button is pressed. Then when the OK button is pressed I iterate through all the controls and set the CausesValidation flag back to true and then call the form's ValidateChildren() method. This has the desired effect of causing the validation to occur on all of the controls after, and only after the OK button is pressed but the result is exactly the same as when I used the binding.WriteValue(). Immediately after the first control updates the data source, every other bound control on the form reverts back to its original value.
I am developing a DLL which is loaded into a Tab page in a Enteprise application.
A ListBox control (single select) has an event on listBox_SelectedValueChanged where the use choosed between different "Display Styles" which when changes fires a sub-routine to reload a DataViewGrid control with different information. Code is below for this:
private void listBox_SelectedValueChanged(object sender, EventArgs e)
{
MessageBox.Show("LBSVC Value:" + listBoxDisplayStyles.SelectedValue + " -- Index:" + listBoxDisplayStyles.SelectedIndex);
if (listBoxDisplayStyles.SelectedValue != null)
PatientChanged(true); // true = force a refresh
}
Now inconsistently when finished interacting with DGV control (no editing, just scrolling and ToolTip triggering to show extended information on the cells) I move the mouse back over the listbox control and click a different line to. The new listbox line becomes current (selection bar appears), but the event does not seem to be triggered (ie the MessageBox does not appear and nothing happens.
Why don't you try SelectedIndexChanged event instead. Therein you can still use listBox.SelectedValue to fetch current value and act accordingly.
BTW it looks like you're working with more than one ListBox here. The event handler uses the object name listBox whereas the event body uses listBoxDisplayStyles. That might have something to do with the problem you're facing. But first try SelectedIndexChanged and let us know.
While developing a simple Windows Form UI applications, I am trying to create an effect to show and close dropdown on mouse events.
Like I can open the dropdown on MouseMove event by setting comboBox.DroppedDown = true;
However, this same is not working when I set comboBox.DroppedDown = false; on MouseLeave event to close it.
No idea what exactly is needs to be done here.
The problem is on MouseLeave the dropdown does not lose focus and hence unless you select one item from list, it does not close. It waits for user to select an item from list.
If it can lose focus on MouseLeave, would work.
Any suggestions please.
First of all I must say that I am not an experienced programmer and I just started with WPF.
I know this question is two years old but I had the same issue and I found I can close the drop down list of the ComboBox using the event IsMouseDirectlyOverChanged. What was really annoying for me was that I had a ComboBox and a button, and If the drop down menu was opened without making a selection and I wanted to click the button, nothing happens at the first click because at the first click the drop down menu was closing. After this I could click on the button.
For me it's working fine: the drop down list close if I move the mouse in any direction (up, left, down, right) and a message is append to a textbox control. I don't know if this event is something new or it could be used 2 years ago too.
private void comPortList_IsMouseDirectlyOverChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (comPortList.IsDropDownOpen==true)
{
txtMsgBox.AppendText("MouseDirectlyOverChanged\n");
txtMsgBox.ScrollToEnd();
comPortList.IsDropDownOpen = false;
}
}
This event triggers when your mouse pointer is over the opened ComboBox. If you don't open the drop down list, it will not trigger.
Another thing that I've seen is that this event triggers when you enter over the opened ComboBox and also when you leave it. If I append the text before checking if the IsDropDownOpen property is true, the text "MouseDirectlyOverChanged" will appear twice in my textbox when I the mouse pointer leaves the oppened ComboBox.
If i comment the line:
comPortList.IsDropDownOpen = false;
and leave the AppendText and ScrollToEnd before if, the text will append only once.
I hope this helps :)
It sounds to me like you need to be using the MouseEnter event and not MouseMove. The reason it wouldn't work on MouseLeave is because your mouse is moving, and that will just set it to true again.
I have a listview control in my windows application, which is populated with some set of items. I will make the selection of an item programmatically by setting ListViewItem.Selected property to true. But I want to prevent the user from selecting an item in the listview. i.e., it should be always selected programmatically. I can prevent the user selection by disabling the control, but disabling the control will also disable the scroll bars which is not correct.
Even I have created a custom listview control and implemented a ItemSelectionChanging eventhandler using WndProc check link, using which i can cancel the event as shown below,
private void lstLiveTables_ItemSelectionChanging(object sender, ListViewExItemSelectionChangingEventArgs e)
{
e.Cancel = true;
}
But again, this will cancel the event, even for an item selected programmatically. My question, is there anyway to identify whether the selection is made manually (by user) or programmatically in SelectedIndexChanged or using WndProc Message.
Note: If it is required, I will upload the code of CustomListView control.
Update 1
Thanks emartel. It was a good thought. Even I tried to achieve the same thing by subscribing to the event only before selecting the item and removed it immediately after selecting. By this way, upon selection the event will be immediately triggered and it will continue. This is working fine.
this.lstTables.SelectedIndexChanged += new System.EventHandler(this.lstTables_SelectedIndexChanged);
item.Selected = true;
this.lstTables.SelectedIndexChanged -= new System.EventHandler(this.lstTables_SelectedIndexChanged);
But again I have a problem that, if the user selects an item manually, nothing will happen (no event will be triggered) but the item alone will be highlighted. Once an item is highlighted and if i try to select the same item programmatically nothing is happening i.e., the SelectedIndexChanged event is not getting triggered for that item as it is already highlighted.
Note: Same behavior even if I follow the Flag approach suggested by you.
Update 2
I can solve this issue by having my own method instead of handling through events as emartel's suggestion. But my question is, according to my update 1, is there anyway to trigger the SelectedIndexChanged event when the item is highlighted but not actually selected?
public FrmTest()
{
list.ItemSelectionChanged += list_ItemSelectionChanged;
}
private bool changing;
private void list_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (changing)
return;
if (e.Item == nonSelectableListItem)
{
changing = true;
nonSelectableListItem.Selected = false;
changing = false;
}
}
Sample:
Well, an easy solution would be to keep a flag saying that you are programmatically changing the selection and to allow the event to pass, and reset the flag when you're done
Edit: if you, and only you, can change the selection, and you do this programmatically, so you have control over where and when this happens, why do you even need the EventHandler? Why not call a method to do whatever processing you want to happen?
One dirty way to do that is to keep list of selected items and refresh selection every time it changes other way than from your code.
There is also an ItemSelectionChanged event which is raised separately for every item whose selection state have changed. You can probably flip the selection state back it this event.
You may also take a look on Better ListView Express control. It have a read-only mode, so that user cannot change the selection. Its setup is very simple:
listView.ReadOnly = true;
The full version also supports custom non-selectable items. Simply setting:
listView.Items[0].Selectable = false;
make the first non-selectable (by the user).
You can still select items from code, of course.
The following image shows non-selectable items in action (they are marked by gray color):
i have tree node in my app that was created by dynamically.when right click what ever node i want to get node text that was clicked.i use that value for my futher processing .i have tried using selected node property and it not work some times.
thanks in advance
Code:
public void CmsAppList_RightClicked(object sender, MouseEventArgs e)
{
AddUser _addUser = new AddUser(this.Text); // i want to get that value to this constructor
_addUser.ShowDialog();
}
This is a known issue with most of the list controls, to work around this add an event handler to treeview's MouseDown event and set the selected node on right click, as follows. My treeview name is treeView1 just change accordingly.
private void treeView1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
treeView1.SelectedNode = treeView1.GetNodeAt(e.Location);
}
Now selectednode should always reflect the node you clicked last.
Edit (To correct This is known issue and saying This is by design and right)
I've been thinking about updating this answer, becuase I realized what I said about this being known issue is wrong on multiple list controls.
Let's say it is known issue and we fix it then right click and left click have similar behavior except that right click does everything(that left click does) and then opens up context menu. This sounds fine till we carefully look at context menu(right click) nature, lets assume you select 15 files and you click (left) on 16th file the selection is lost :) so you select 15 files and the right click the context menu and operations are applicable to all the 15 files selected.
This is the reason right click shouldn't change the selection in any view (in listbox or treeview or explorer widnow). If it does then multiselect and control+select features would break, and ultimately special meaning for right click being context specific actions would be lost. That is the reason the right click wouldn't select the clicked node and that is right. The code provided above is for for specific purpose of enabling right click selection. And consider the UX impact with this kind of work around or aberrant behavior.