Set panel visiblity on Escape key press - c#

Lets say I have a windows form and it has two panels. Main panel and popup panel.When specific button click main panel will disable and popup panel will be visible.
My question is when user press escape key i want to set visibility of popup panel to false and enable main panel.

bool bPanelFocus;
private void cancelButon_Click(object sender, EventArgs e)
{
if (popuppanel.Visible == true && bPanelFocus)
{
popuppanel.Visible = false;
mainpanel.Visible = true;
return;
}
//your code for the cancel button
}
Since you have a cancel button on the form, it will trigger the click event on that button when you press the Esc button. On your cancel button's click event, add a validation to check if the pop up panel is visible, also you might need a flag to check if the user has focus on the panel otherwise proceed with the cancel button's procedures.

Related

Cannot keep OnClick event after visibilty change

Just wondering if someone else can recreate this or is it just me :)
Drop a panel on the form
Put a button on the panel
Create click of button "I am Button"
Above works fine
Add onmouseleave to panel set button visible to false
Add onmouseenter to panel set button visible to true
Now if you move mouse in and out of panel the button will become visible false. Pefect.
Now move mouse back intp panel and button becomes visible. Perfect.
Clicking on button now does nothing (Lost on Click Event?)
Breakpoint in onclick never fires.
Is this a concept that cannot be done?
'Update' It wont let me post long comment.
First of all thanks for the quick responses.
I did not include code because this was in a very large project so i recreated it with a brand new app.
C# WinForm with one panel and one button on the panel.
I did not try to click on an invible button. Not only can i see the button but can see it respond to bing clicked.
#steve. Good point, The button is well inside of the panel but i see where you are going. I just performed a new test.
If i move the mouse in and out of the panel the button will show and hide perfectly.
After this, hitting enter on the button will excute onclick but the mouse will not. (I suppose this has something to do with only one button and it is default.)
What prompts the mouse to not fire the click event is beyond me.
Very Strange.
What i am trying to achieve:
An area on the screen that when the mouse enters this area a group of buttons appear so they can be used.
when the mouse leaves this area the buttons will dissapear. As my original post stated button works fine if visiblity does not change.
I suppose the your code has the following problem:
You receive the mouseenter event on the panel and you make the button
visible
You move the mouse over the button
This last action triggers the mouseleave event on the panel.
As a consequence your button becomes invisible.
But making the button invisible triggers a mouseenter over the panel and in a blink the button is again visible and causing a mouseleave on the panel.
An infinite loop between these two events starts.
So the click event is not lost, simply it will never trigger because the form engine is busy hiding and showing the button control.
I have reproduced the situation and fixed it adding an event handler for the MouseMove event. In this event I set a variable to block the infinite loop between the two events...
This is my example to adapt to your real code, try it in LinqPad
public class Form1 : Form
{
Button b1 = new Button();
Panel p1 = new Panel();
bool stillOnPanel = false;
public Form1()
{
b1.Text = "ClickMe";
b1.Click += onClick;
b1.Visible = false;
p1.MouseEnter += onEnter;
p1.MouseLeave += onLeave;
p1.MouseMove += onMove;
p1.BorderStyle = BorderStyle.FixedSingle;
p1.Size = new Size(150,100);
this.Controls.Add(p1);
p1.Controls.Add(b1);
}
void onClick(object sender, EventArgs e)
{
Console.WriteLine("Clicked");
}
void onMove(object sender, MouseEventArgs e)
{
//Check if we are still over the panel area
stillOnPanel = b1.ClientRectangle.Contains(p1.PointToClient(Cursor.Position));
}
void onEnter(object sender, EventArgs e)
{
if (!b1.Visible)
{
b1.Visible = true;
}
}
void onLeave(object sender, EventArgs e)
{
// Do not hide the button if we are over it, let it click....
if (b1.Visible && !stillOnPanel)
{
b1.Visible = false;
}
}
}

WPF Lost-Focus issue in same control

I have a small problem with focusing in .net/wpf. I have written a custom user control which contains a TextBox and a SearchButton. The user-control has a lost focus event, which validate the content of the textbox if the focus is leaving. But now I have the problem, if I click on my search button, the lost focus event of the user control gets fired, even if I click on the button in the custom user control. (The button additionally has the option TabStop="False":
The problem is, that I don't want to fire the event if I click on the button.
Set
Focusable="False"
of your search button and the TextBox will not lose the focus because the button doesn't get the focus.
You can Do this Check in Event like this
protected void LostFocusEvent(object sender, RoutedEventArgs e)
{
if(textBox.Text.Length>0)
{
// if there is any character in TextBox
return;
}
// your validation Code goes here
}

Duplication Controls Winforms

I have such a situation here.
Let's say we have three button on our Form, and one Control, which is Panel, and which is hidden when the Form is loaded. Here is it
When I click on Button 1, that Panel have to be shown under Button1, when clicking on Button2, it have to be showned under Button2 and so on. Let's say I clicked on Button2.
Now I want that same Panel to show, when Clicking on Button1 and not at the same place. I need the same panel to be showed under buttons when clicking them.For example, the same panel is showing when clicking button 3
I made this only working for only one button. I can't have 2 controls with same attributes, but I need somehow to duplicate that control.I And I think it have to be done with UserControl.
private void btn_click(Control sender, EventArgs e)
{
var btn = sender as Button;
panel1.Left = btn.Left;
}
now assign this even handler to click event for all buttons.
The var btn.... line will represent the button that was clicked, or the control that triggered the event, so from there you can set the panel's location.

Restrict tab order to a single user control

I have a user control that behaves as a floating control, and I would like to restrict the tab order only to my user control when its visible. Basically what I need is to have a control that behaves like a borderless Form. Actually it was a Form, but I needed to preserve the Focus in the MainForm window, so I had to change it to be a UserControl.
So, imagine a Form A (MainForm), and my UserControl B. B is a child control of A. Suppose that Form A has a button and a TextBox, and the control B also has a button and a Textbox. The secuence that currenly occurs is the following
What currently happens (natural tab order behavior):
When only A is visible (B is not visible):
1. The user manually focuses A textbox
2. Press tab key
3. A button is focused
When A is visible and also B is visible: (the natural tab order key is the following):
1. The user manually focuses B textbox
2. Press tab key
3. B button is focused
4. Press tab key
5. A textbox is focused
6. Press tab key
7. A button is focused
What I need (I need to change my user control to preserve the focus):
What I really need is that the B control preserves the tab order inside it, so what I need is with when B control is visible:
1. The user manually focuses B texbox
2. Press tab key
3. B button is focused
4. Press tab key
5. B textbox is focused
You can override the Controls' KeyDown event and manually move the focus over to the Control that should receive focus.
Aside from that, I agree with Will Hughes that it might break navigation...
I'm assuming you have some button you press that toggles the visibility of your B user control. And if it is visible and has focus then it keeps focus. It loses focus only when you toggle it to hidden. If that's the case, you could try this code in your A form which will keep your focus in the user control unless you hide the user control:
// store when we last clicked the toggle B user control visibility
private Stopwatch _sinceLastMouseClick;
public Form1()
{
InitializeComponent();
// instantiate the stopwatch and start it ticking
_sinceLastMouseClick = new Stopwatch();
_sinceLastMouseClick.Start();
}
The button that toggles the visibility on your floating B control's click handler:
private void btnToggleBUserControlVisibility_Click(object sender, EventArgs e)
{
// reset the stopwatch because we just clicked it
_sinceLastMouseClick.Restart();
myUserControl1.Visible = !myUserControl1.Visible;
}
In your parent A form, handle the floating user control's Leave event:
private void myUserControl1_Leave(object sender, EventArgs e)
{
// see if the mouse is over the toggle button
Point ptMouse = System.Windows.Forms.Control.MousePosition;
Point ptClient = this.PointToClient(ptMouse);
// if the mouse is NOT hovering over the toggle button and has NOT just clicked it,
// then keep the focus in the user control.
// We use the stopwatch to make sure that not only are we hovering over the button
// but that we also clicked it, too
if (btnToggleBUserControlVisibility != this.GetChildAtPoint(ptClient) ||
_sinceLastMouseClick.ElapsedMilliseconds > 100)
{
myUserControl1.Focus();
}
}
Finally I solved the issue including the following code in the parent control:
private int WM_KEYDOWN = 0x100;
public override bool PreProcessMessage(ref Message msg)
{
Keys key = (Keys)msg.WParam.ToInt32();
if (msg.Msg == WM_KEYDOWN && key == Keys.Tab)
{
if (itemSearchControl.Visible)
{
bool moveForward = !IsShiftKeyPressed();
bool result = itemSearchControl.SelectNextControl(itemSearchControl.ActiveControl, true, true, true, true);
return true;
}
}
return base.PreProcessMessage(ref msg);
}
From another question, add this to your UserControl xaml.
KeyboardNavigation.TabNavigation="Cycle"
Restrict tab order to a single user control (WPF)

Validating Data In A WinForm

I have created a dialog box in my WinForms application. This has many text boxes and ok/cancel buttons. When the user clicks ok, I only want the dialog box to close if all entries are valid. I can see how to do this with the "Validating" events for each control separately. That is fine. But these only seem to fire when a control loses focus. However, empty text boxes in my dialog are also invalid input which means the user may never have focused on that control. I would prefer to just validate all controls on clicking OK.
I can't work out how to do this though. Overriding the onclick of the OK button doesn't seem to have an option for stopping the window from closing. The Form IsClosing event does by setting Cancel = true. But this doesn't seem to be able to distinguish between whether the OK or Cancel button is clicked. Obviously if the cancel button is clicked I don't care about validation and want to allow the form to close regardless.
What is the best approach for doing this?]
Update:
I already had CausesValidation set to true on both my form and ok button but my validation event does not get fired when I click the ok button. I mention this as it was suggested as a solution below.
Please select the form > Set the property CausesValidation to true
Select OK button and again set property CausesValidation to true
and then it will take care of all the validations.
Important points:
1) You must mention e.Cancel=true in all the validating eventhandlers
2) If your buttons are in panels then you must set panels (or any parent control's) CausesValidation property to true
Edit:
3) Validate fires just before loss of focus. While pressing Enter will
cause the default button to Click, it doesn't move the focus to that
button, hence no validation event will be fired if you have set forms AcceptButton Property to OK button
First make sure to cancel the validation when any of the textboxes have validation errors. For example:
private void nameTextBox_Validating(object sender, CancelEventArgs e) {
if (nameTextBox.Text.Length == 0)
{
e.Cancel = true;
return;
}
}
Now add the following code to the beginning of the ok button action:
if (!ValidateChildren())
return;
This will trigger the validation event for all controls on the form,
You can also use this simple code. just introducing a simple Boolean variable named hasError can do the job.
public partial class Form1 : Form
{
private bool hasError;
public Form1()
{
InitializeComponent();
}
private void OkBtn_Click(object sender, EventArgs e)
{
errorProvider1.Clear(); hasError=false;
if (ValidateTxt.Text.Length == 0)
{
errorProvider1.SetError(ValidateTxt, "must have a value");
hasError=true;
}
if (!hasError)
{
//Do what you want to do and close your application
Close();
}
}
private void CancelBtn_Click(object sender, EventArgs e)
{
Close();
}
}

Categories