I am new to using Event Handling in C# .NET, and I am trying to understand the behavior behind some simple code that I am experimenting with. I am working with a more complicated example, but I am hoping I will get a more focused answer if I simplify the example.
I have the following code which defines a main window with a ListBox that is initialized with values, and a panel in the window. I am working with dragging the ListBox Items and dropping them in the panel. To signify that the panel is reading the DragDrop event, I am simply just changing the background color.
My problem is, it is not changing the background color when I drop the values, hence, the DragDrop is not working. I know this is a bit exaggerated, but I am trying to understand why its not working.
Here is the following code that I am using.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Allow Panel to accept dropped values
this.panel1.AllowDrop = true;
//Initialize ListBox with sample values
listBox1.Items.Add("First Name");
listBox1.Items.Add("Last Name");
listBox1.Items.Add("Phone");
//Setup DragDrop Event Handler - is this correct, or even needed?
this.panel1.DragDrop += new DragEventHandler(panel1_DragDrop);
}
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
ListBox box = (ListBox)sender;
String selectedValue = box.Text;
DoDragDrop(selectedValue.ToString(), DragDropEffects.Copy);
}
private void panel1_DragDrop(object sender, DragEventArgs e)
{
//Change Background color to signify value has been dropped
((Panel)sender).BackColor = Color.Black;
}
}
I realize this is an oversimplified example. If you see what I am doing wrong, then please let me know.
EDIT To give an example of why I am confused, I change this example around to put the dragged ListBox Item text into a Textbox when the DragOver event was fired, and it worked fine, but when I tried to do the same thing when they dropped the values over the textbox, I could not get it to work.
Handle the panel's DragEnter event and set e.Effects to something other than None.
Related
I have the following problem: I have a panel which has a specific color, say red.
When the user presses his mouse, the color of this panel gets stored in a variable. Then the user moves, his mouse still pressed, over to another panel. When he releases the mouse there, this panel should get the background color of the first that had been stored in the variable. My code looks something like this:
public Color currentColor;
private void ColorPickMouseDown(object sender, MouseEventArgs e)
{
Panel pnlSender = (Panel)sender;
currentColor = pnlSender.BackColor;
}
private void AttempsColorChanger(object sender, MouseEventArgs e)
{
Panel pnl = (Panel)sender;
pnl.BackColor = currentColor;
}
I need to identify the sender first because there are many possible panels that can trigger this event. The first MouseDown method works totally fine, the color is stored nicely in the variable. The secon one however doesn't even get triggered when the user does what I described above. When the ser clicks on the second panel, it works (there is an MouseUp part in a click aswell I guess).
What's wrong here? Why is the event not triggered when the user holds the mouse key down before?
(This answer assumes you are using Windows Forms.)
It could be that you need to capture the mouse by setting this.Capture = true in the MouseDown of the source control. (See Control.Capture)
If you did that, the source window would get the MouseUp event, and it would be the source window that had to determine the destination window under the mouse coords. You can do that using Control.GetChildAtPoint() (see this answer on Stack Overflow).
Use Windows Forms Drag and Drop Support Instead! <- Click for more info
I'm going to suggest you bite the bullet and use the .Net Drag and Drop methods to do this. It requires some reading up, but it will be much better to use it.
You start a drag in response to a MouseDown event by calling Control.DoDragDrop().
Then you need to handle the Control.DragDrop event in the drop target control.
There's a few more things you might need to do to set it up; see the Control.DoDragDrop() documentation for an example.
(For WPF drag and drop support, see here.)
when your mouse enter the target control , mouse down triggerd ang get target BackColor! you need add an boolean flag to your code :
public Color currentColor;
bool flag=false;
private void ColorPickMouseDown(object sender, MouseEventArgs e)
{
if(flag==false)
{
flag=true
Panel pnlSender = (Panel)sender;
currentColor = pnlSender.BackColor;
}
}
//assume mouse up for panles
private void AttempsColorChanger(object sender, MouseEventArgs e)
{
if(flag==true)
{
Panel pnl = (Panel)sender;
pnl.BackColor = currentColor;
flag=flase;
}
}
and also you need change your flag in mouseMove( if )
As I mentioned in my comment Mouse Events are captured by the originating control, You would probably be better off using the DragDrop functionality built into Windows Forms. Something like this should work for you. I assigned common event handlers, so they can be assigned to all of your panels and just work.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void panel_MouseDown(object sender, MouseEventArgs e)
{
((Control)sender).DoDragDrop(((Control)sender).BackColor,DragDropEffects.All);
}
private void panel_DragDrop(object sender, DragEventArgs e)
{
((Control)sender).BackColor = (Color)e.Data.GetData(BackColor.GetType());
}
private void panel_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
}
I know it's an old question but I had the same issue and none of the above answers worked for me. In my case I had to handle the MouseMove event in the target control and check for the mouse to be released. I did set 'BringToFront' on my target panel just in case that helped at all.
public Color currentColor;
private void ColorPickMouseDown(object sender, MouseEventArgs e)
{
Panel pnlSender = (Panel)sender;
currentColor = pnlSender.BackColor;
}
private void panelTarget_MouseMove(object sender, MouseEventArgs e)
{
//the mouse button is released
if (SortMouseLocation == Point.Empty)
{
Panel pnl = (Panel)sender;
pnl.BackColor = currentColor;
}
}
I'm wondering if it's possible to use ToolTip.SetToolTip or something similar to open a control as a tooltip instead of just a string (i.e. SetToolTip(controlToWhichToAdd, panelToDisplayAsToolTip) instead of passing a string as your second parameter).
If this isn't possible I'm guessing next best thing is displaying a panel on the mouse location on mouse_enter event on the control and removing it (or making it invisible) on mouse_leave.
Or are there other practices that make this possible in an easier way?
This is not possible out of the box. You have two choices. First option is to override the Draw Event, which will let you customize how the tooltip looks. Here is an example of this. Be sure you set the OwnerDraw property to true if you use this method!
Although the first method will work if you just need some simple customization, the second option will work best if you need more flexible options. The second option is to do what you already suggested and create your own sort of tooltip. Simply put, you would first create an event handler for the MouseEnter event. When that event fires, you'd enable a Timer. This timer would be the delay that occurs before the tooltip is show. Then finally, you'd just make your panel appear at the mouse coordinates.
Suppose you have a form with a button and timer on it and you want the button to have a tooltip that is a panel:
public partial class Form1 : Form
{
private Panel _myToolTipPanel;
private void Form1_Load(object sender, EventArgs e)
{
_myToolTipPanel = new Panel {Visible = false};
Controls.Add(_myToolTipPanel);
Label myLabel = new Label();
myLabel.Text = "Testing";
_myToolTipPanel.Controls.Add(myLabel);
}
private void button1_MouseEnter(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void button1_MouseLeave(object sender, EventArgs e)
{
timer1.Enabled = false;
_myToolTipPanel.Visible = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Enabled = false;
Point position = Cursor.Position;
Point formPoisition = PointToClient(position);
_myToolTipPanel.Visible = true;
_myToolTipPanel.Location = formPoisition;
}
}
Now of course you will have to do some beautifying of the tooltip, but this is the general idea!
One Approach could be inheriting the ToolTip control and then override the SetToolTip and Show methods . Inside the SetToolTip the private method - SetToolTipInternal needs to be re-written , but most of the functionality could be reuse - it uses the Mouse Events ( leave , move) to bind region. but since tooltip uses internal's of windows to show the baloon window. you will have to override quite a bit of code.
but this could be time consuming and needs quite a bit of testing.
You could write a handler for the Tooltip.Popup event, and cancel the popup to display your own panel.
You'd need to clean it up at the appropriate time, though.
For example:
private void ToolTip1_Popup(Object sender, PopupEventArgs e)
{
e.Cancel = true;
//Do work here to display whatever control you'd like
}
If you're just looking for more formatting options in the tooltip display, an alternative is something like this CodeProject entry, which implements an HTML-enabled tooltip:
I've got a combobox that opens a new form window with a datagridview, and I want the users to choose the items through that datagridview rather than through the combobox. I've got this code to achieve that:
private void comboBox1_DropDown(object sender, EventArgs e)
{
valSel.incBox = (ComboBox)sender;
valSel.Show();
if (this.comboBox1.DroppedDown)
{
MessageBox.Show("test");
SendMessage(this.comboBox1.Handle, CB_SHOWDROPDOWN, 0, 0);
}
}
As you see I'm also trying to hide the dropdown of the combobox but it isn't working. I assume it's because the combobox hasn't actually "dropped down" yet, so that part of the code is never run.
Is there an event or something I can cell when the combobox has fully "dropped down" so i can send the message to close it again?
You should be able to simply set the height of the ComboBox to something really small. Last time I looked at it, this determined the height of the popup part (the actual height of the control is determined by the UI/font size).
The more elegant way, however, would be using a custom control that just mimics the appearance of dropdown boxes (I'm rather sure that can be done some easy way).
In comboBox1.Enter set the focus to a different control if condition is met.
private void comboBox1_Enter(object sender, EventArgs e)
{
if (comboBox1.Items.Count < 1)
{
comboBox1.DroppedDown = false;
comboBox2.Focus();
MessageBox.Show("Select a list first");
comboBox2.DroppedDown = true;
}
}
1) create a KeyPress event on ComboBox from the properties.
2) write code
private void cmbClientId_KeyPress(object sender, KeyPressEventArgs e)
{
((ComboBox)sender).DroppedDown = false;
}
I have a tree view on the left side. Selecting a node displays relevant information in a form on the right side.
Would I be able to keep the tree and any one control (textbox, combobox, checkbox) on the right in focus at the same time? This will enable a user to select a field, make a change, select another node, and without having to go back and select the same field again, just type and change the value of the same field.
Thanx.
EDIT
I suppose one could implement such behaviour manually:
private Control __cFocus;
private void {anyControl}_Focus(object sender, EventArgs e)
{
__cFocus = (Control)sender;
}
private void treeView1_AfterSelect(object sender, EventArgs e)
{
__cFocus.Focus();
}
I was just wondering if there exists an automatic / more elegant solution
EDIT 2
Ok, so it seems I'll have to implement it manually. Manual implementation it is then. However, now there seem to be another problem; not sure if I should ask this as a separate question.
When selecting a node the textbox gains focus as intended, but only when using the keyboard. It doesn't work when selecting a node with the mouse. First I thought that it might be a mouse event that's interfering, but stepping revealed that the MouseUp event fired first and then the AfterSelect event which sets the focus, so I don't think it's interfering. The textbox's Enter event is also fired, but for some reason it loses focus again to the tree.
Thanx
no, you cannot keep two controls in focus at the same time. But what you can do is set the focus to the target control in the treeview AfterSelect event
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
textBox1.Focus();
textBox1.SelectAll();
}
then in your textbox leave, save the changes, like so:
private void textBox1_Leave(object sender, EventArgs e)
{
//save changes here
}
this way, everytime you select an item in the treeview, check your textbox for change and save as needed, then you will refocus on the textbox for your next edit
There only can be one element having the focus!
But I have an idea for you that might solve your problem. Assuming you have a window with a TreeView and a TextBox. Set the HideSelection property of the TreeView to false and subscribe the AfterSelect event (like edeperson already answered) like this:
private void OnTreeViewAfterSelect(object sender, TreeViewEventArgs e)
{
textBox1.Text = e.Node.Text;
textBox1.Focus();
}
Then subscribe the KeyDown event of the TextBox and do following in the event method:
private void OnTextBoxKeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == Keys.Up) || (e.KeyCode == Keys.Down))
{
treeView1.Focus();
SendKeys.Send(e.KeyCode == Keys.Up ? "{UP}" : "{DOWN}");
}
}
At last subscribe the Leave event of the TextBox and do following in the event method:
private void OnTextBoxLeave(object sender, EventArgs e)
{
if (treeView1.SelectedNode != null)
{
treeView1.SelectedNode.Text = textBox1.Text;
}
}
And, voilá it should work like you expected it...
If you want to focus on it , you can use usercontrol. you can put your textbox on usercontrol and set focus of this textbox on usercontrol using set properties on treeview select.
No you may not, only one control may be in focus at any given time.
See Moonlight's comment for one way to achieve the behavior that you seek.
I have a combo box. It must display its content, when focused and its value changed as well.
I wrote this code in its Value Change event:
if(combo1.Focused)
combo1.DroppedDown=true;
But it doesn't work!
what's your solution?
What Event handler are you putting that code in? Assuming that you want to show the drop down when the user types in the edit box part of the combo just handle the TextChanged event and put that code inside there and it should work.
If I understand your requirement correctly, when the combobox gets focus you want the drop down list to show. That can be achieved as follows
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.GotFocus += new EventHandler(comboBox1_GotFocus);
}
void comboBox1_GotFocus(object sender, EventArgs e)
{
comboBox1.DroppedDown = true;
}