I have an event that fires using the AfterSelect Event, and this works just fine, but I do not want this event to fire if the user either checks or unchecks the checkbox of this or any node in the tree. Alternatively, the event can fire, but then I need to know inside the event if it was fired as a result of a check or uncheck of the checkbox. I have tried using NodeMouseClick instead but I get the same unwanted result, and I have also tried removing the event handler using BeforeCheck and adding it back using AfterCheck, like so:
private void MyTree_BeforeCheck(object sender, TreeViewCancelEventArgs e)
{
this.MyTree.AfterSelect -= new System.Windows.Forms.TreeViewEventHandler(this.MyTree_AfterSelect);
}
private void MyTree_AfterCheck(object sender, TreeViewEventArgs e)
{
this.MyTree.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.MyTree_AfterSelect);
}
private void MyTree_AfterSelect(object sender, TreeViewEventArgs e)
{
ShowMyInfo(e.Node);
}
but the AfterSelect event still fires.
I cannot rely on AfterCheck because then it won't fire if you simply select the node. I also cannot rely on checking if e.Node.Selected == true, because the node might already be checked, and I want the event to fire if the node is in fact deliberately selected.
Is there any event handler I can use that will trigger only if a node is SELECTED, and not CHECKED or UNCHECKED, or any way I can detect if a node that's just been selected has been checked or unchecked.
Using Visual Studio 2019 with a C# WinForms .NET Framework application.
As #Jimi and #dr.null have pointed out, I am using the right event after all. AfterSelect will not fire just because you checked or unchecked the checkbox.
The problem that I had was that I have code that will select a node if you right click it (right clicking does not automatically select a node).
Old Code:
private void MyTree_MouseDown(object sender, MouseEventArgs e)
{
MyTree.SelectedNode = MyTree.GetNodeAt(e.X, e.Y);
}
New Code:
private void MyTree_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right) MyTree.SelectedNode = MyTree.GetNodeAt(e.X, e.Y);
}
I was inadvertently firing off my own event because I did not check for which mouse button was clicked on the MouseDown event. Thank you for the help!
Related
I am moving a TreeNode in a Windows Forms TreeView control as a consequence of a DragDrop event:
void treeViewDragDrop(object sender, DragEventArgs e)
{
// ...
sourceNode.Remove();
targetNode.Nodes.Add(sourceNode);
}
However, the Remove call triggers the AfterSelect event of the TreeView, which I need to react to if the selection really changes.
But in this case, the apparent selection change is only a result of temporarily removing the node. I don't want the selection to change at all after the node has finally moved to its target location in the tree.
So what would be the correct way to deal with that situation, i.e. how to suppress selection changes due to moving nodes?
If you do not set selection programmatically, you can cancel the selection in BeforeSelect event if the action is not user-generated:
private void TreeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e)
{
if (e.Action == TreeViewAction.Unknown)
e.Cancel=true;
}
If you change selection programmatically, you may use a simple workaround by extending the TreeView class and setting a sort of "flag":
public class MyTreeViwe : TreeView
{
public bool IsSuspendSelection { get; set; }
protected override void OnBeforeSelect(TreeViewCancelEventArgs e)
{
if (IsSuspendSelection)
e.Cancel = true;
else base.OnBeforeSelect(e);
}
}
then do:
var tv = sourceNode.TreeView;
tv.IsSuspendSelection=true;
sourceNode.Remove();
tv.IsSuspendSelection=false;
You could also unsubscribe and then subscribe again to the AfterSelect event on sourceNode.TreeView, but I personally find this method accident-prone. There's no way to know if a given delegate is currently subscribing to a given event, and how many times. You may end up subscribing to the event multiple times and then your AfterSelect delegate method will run more than once.
I am self teaching myself C# and ran into a problem I haven't seem to find an answer too. I have a Form that when I mouse click the check box the state goes to true but also immediately triggers the mouse click event I have code follows:
private void uxCheckBoxMouseClick(object sender, MouseEventArgs e)
{
//MouseEventArgs me = (MouseEventArgs) e;
if (uxMouseCopyCheckBox.Checked)
{
MessageBox.Show("Test");
uxMouseCopyCheckBox.Checked = false;
}
}
I have searched the stack overflow and Google and found similar items but not in C# but no luck on the fixed solution. What I want to do it use the first click to change the check box to true without triggering the mouse click event. I want to delay the event to the 2nd mouse click and not the first.
I have tried the following:
for loop
Clicks == 2 with if statement
subscribing but at a loss on what to use
Instead of the Click event you could subsribe to the CheckedChanged event :
The Handler will look look exactly like yours :
private void uxMouseCopyCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (!uxMouseCopyCheckBox.Checked)
{
MessageBox.Show("Test");
uxMouseCopyCheckBox.Checked = false;
}
}
The only difference is that we want the Message box to be shwon only on the second click so when you will uncheck the checkbox.
Be careful though, if you change the default state of the checkbox, it will no longer work.
If you want a really robust solution Grant's one is IMHO the best, mine was just here to show you how to adapt your code for it to work
Just use a boolean variable as a flag.
private bool wasAlreadyClickedOnce;
private void uxCheckBoxMouseClick(object sender, MouseEventArgs e)
{
if (!wasAlreadyClickedOnce)
{
wasAlreadyClickedOnce = true;
return;
}
if (uxMouseCopyCheckBox.Checked)
{
MessageBox.Show("Test");
uxMouseCopyCheckBox.Checked = false;
}
}
Try using the Click event instead of CheckedChanged event to check or uncheck the CheckBox and then you can use the MouseClick event for other stuff.
I'm using a WPF DataGrid with c#/xaml in Visual Studio 2013.
With SelectionMode="Extended", I'm able to multi-select rows in the grid.
I have a requirement where clicks on one of the columns of the grid are to be ignored relative to row selection.
I setup a PreviewMouseLeftButtonDown event that gets called.
Since it's a preview event, at the time of the event is processed, the selection in the grid hasn't changed yet.
I'm able to determine the row and column of the click, so I can determine a click has been made in a column that I don't want
I want to be able to abort the click event at that point so that no change is made to the current selected items in the grid. Is that possible?
In the mouse down event I tried something like:
private void GridCtrl_MouseDown(object sender, MouseButtonEventArgs e)
{
// ... Other code
e.Handled = true;
}
But, despite being marked as handled, it still continues and performs the row selection.
I also have a 'SelectionChanged' event that I see that it later gets into.
I think you actually need to handle both tunneling events - one for PreviewLeftMOuseButtonDown and another for PreviewSelectionChanged.
My advice is create a flag, let's call it:
bool _cancelSelectionChange = false;
Then, in your Mouse handler:
private void GridCtrl_MouseDown(object sender, MouseButtonEventArgs e)
{
_cancelSelectionChange = false;
// ... Other code
_cancelSelectionChange = true;
e.Handled = true;
}
Finally, in your selection change handler for the tunneling event:
private void GridCtrl_PreviewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
e.Handled = _cancelSelectionChange;
}
I am quite new to Winform dev. I have two list boxes. When the user double clicks an item in the first listbox, I want this to be copied to the second list box. The problem is that my double click method never gets fired.
here's my code:
//here I register the event
this.fieldsArea.MouseDoubleClick += new MouseEventHandler(fieldsArea_MouseDoubleClick);
Then here is the double click method:
private void fieldsArea_MouseDoubleClick(object sender, MouseEventArgs e)
{
MessageBox.Show("from method");
int index = fieldsArea.IndexFromPoint(e.Location);
string s = fieldsArea.Items[index].ToString();
selectedFieldsArea.Items.Add(s);
}
So I want the element from fieldsArea to be copied to selectedFieldsArea... The messagebox never shows and in debug I see that I never enter this method...
Am I missing something here?
ps: I have drag drop implemented which works well.
UPDATE: The problem comes from the MouseDown event also being implemented. So here's my mousedown event.
private void fieldsArea_MouseDown(object sender, MouseEventArgs e)
{
if (fieldsArea.Items.Count == 0)
return;
int index = fieldsArea.IndexFromPoint(e.Location);
string s = fieldsArea.Items[index].ToString();
DragDropEffects dde1 = DoDragDrop(s,
DragDropEffects.All);
}
ps: I have drag drop implemented which works well.
That means probably that you have registered a MouseDown event, which interfere with the MouseDoubleclick.
Just for testing purpose, try to delete the Drag&Drop implementation ( unregister the MouseDown event) and then the MouseDoubleclick should work.
Make sure you don't have other Mouse event like MouseClick MouseDown event registered, which could interfere with MouseDoubleclick event.
Update:
Add following code in your MouseDown event handler, you can check if it is a double-click first.
if(e.Clicks>1)
{
int index = fieldsArea.IndexFromPoint(e.Location);
string s = fieldsArea.Items[index].ToString();
selectedFieldsArea.Items.Add(s);
}
so here is your new handler:
private void fieldsArea_MouseDown(object sender, MouseEventArgs e)
{
if (fieldsArea.Items.Count == 0)
return;
int index = fieldsArea.IndexFromPoint(e.Location);
string s = fieldsArea.Items[index].ToString();
if(e.Clicks>1)
{
selectedFieldsArea.Items.Add(s);
}
else
{
DragDropEffects dde1 = DoDragDrop(s,
DragDropEffects.All);
}
}
I believe you may have either "MouseClick/MouseDown" event or "SelectedIndexChanged" event, these events resist to get fire of "MouseDoubleclick" event, so you need to handle them properly. Thanks
I am trying to show a popup menu on my treeview when users right click - allowing them to choose context sensitive actions to apply against the selected node.
At the moment the user has to left click node and then right click to choose.
Is it possible to make a right click on a node select that node - and if so what is the best method to do this.
Both left and right clicks fire a click event and cause the selection to change. However, in certain circumstances (that I haven't yet bothered to trace down) the selection will change from the node that was right clicked to the originally selected node.
In order to make sure that the right click changes the selection, you can forcibly change the selected node by using the MouseDown event:
treeView.MouseDown += (sender, args) =>
treeView.SelectedNode = treeView.GetNodeAt(args.X, args.Y);
A little better, as one of the other posters pointed out, is to use the NodeMouseClick event:
treeView.NodeMouseClick += (sender, args) => treeView.SelectedNode = args.Node;
yes. Here is processing for NodeMouseClick event:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
treeView1.SelectedNode = e.Node;
}
Drag a context menu strip onto the form then:
private void treeView1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
// Display context menu for eg:
ContextMenu1.Show();
}
}