How to prevent user interaction with invisible forms? - c#

In my application there appeared a following problem: certain dialogue forms can be interacted with before they are drawn.
The code goes like:
void FunctionCalledFromButtonPressHandler()
{
var f = new MyDialog();
if (f.ShowDialog() == DialogResult.OK)
{
//do things
}
}
The buttons on the starting form and dialog form (one that loses it) are over each other on the touchscreen. If the plac is clicked over twice, there is a pause corresponding to the load of dialog form, and then, without it being shown, wotk in starting form is continued/
How should i go about preventing such sort of behaviour (that is, apart from removing the delay on the loading of dialog)?

Set 'Button.Enabled = false;' on your starting form inside the launching method.
void FunctionCalledFromButtonPressHandler()
{
YOURBUTTON.Enabled = false;
var f = new MyDialog();
if (f.ShowDialog() == DialogResult.OK)
{
//do things
}
YOURBUTTON.Enabled = true;
}
Then in your dialog form set the other Button.Enabled = false; in the form constructor. Then you can set the button to enabled in the Shown event like this:
void MyDialog_Shown(object sender, EventArgs e)
{
OTHERBUTTON.Enabled = true;
}

Related

Database only updates after closing and opening dialog

I have a DataGridView inside a form that displays data from a database every time I load the page like this:
private void LoadList(string Input)
{
fieldsDataGridView.DataSource = null;
List<Field> fields = new List<Field>();
fields = fieldsData.GetAllByTaskId(Input);
List<FieldsDGViewModel> fdgvm = new List<FieldsDGViewModel>();
foreach (var item in fields)
{
var f = new FieldsDGViewModel
{
Id = item.Id,
Name = item.Name,
Order = item.Order,
IsPrint = item.IsPrint
};
fdgvm.Add(f);
}
fdgvm = fdgvm.OrderBy(x => x.Order).ToList();
fieldsDataGridView.DataSource = fdgvm;
fieldsDataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
fieldsDataGridView.Columns["Id"].Visible = false;
fieldsDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
}
When I double click on an entry in my list, it opens a dialog box containing a form and loads the respective details from that entry. When I save the details, the dialog box closes and in the class where my DataGridView sits, there is this FormClose function that refreshes the DataGridView.
private void FormClosed(object sender, FormClosedEventArgs e)
{
RefreshDataGrid();
RecursiveClearInputs(this.Controls);
fieldIdInput.Text = "";
}
private void RefreshDataGrid()
{
var selected = programInput.SelectedValue;
if (selected != null)
{
var result = programsData.Get(selected.ToString());
if (result != null)
{
programIdInput.Text = result.Id;
LoadList(result.Id);
}
}
if (selected == "-1")
{
RecursiveClearInputs(this.Controls);
programIdInput.Text = "";
fieldIdInput.Text = "";
fieldsDataGridView.DataSource = null;
}
fieldsDataGridView.ClearSelection();
}
However, I am having this issue where the only way that my DataGridView refreshes properly is if I close the main form I am on and reopen it again.
I debugged and managed to capture some results.
Image1: Directly after the Update form is closed. In the fields list, only one entry can have IsPrint = true. However the image shows that both are true.
Image2: After I close and reopen the page containing the DataGridView, it shows this correct result. Only 1 IsPrint = true.
I have tried many methods to solve this issue but I'm not sure why its not refreshing properly.
This is how I open a dialog
EditFields editFields = new EditFields(programIdInput.Text, fieldIdInput.Text, false);
editFields.FormClosed += new FormClosedEventHandler(FormClosed);
editFields.ShowDialog();
EDIT:
I added a dialogresult check but it still doesn't update the datagridview properly. Maybe its a thread issue?
dr = editFields.ShowDialog();
if (dr == DialogResult.OK)
{
RefreshDataGrid();
RecursiveClearInputs(this.Controls);
fieldIdInput.Text = "";
}
I'm just assuming how the OnCklick event looks where you open your Dialog, but I think the problem is that you try to refresh the Datagrid form another Form / Thread. (which will not work)
I suggest you open the dialog form by using ShowDialog and refresh the grid after the Form was closed in the onclick event itself. Try replacing
RefreshDataGrid();
in your FormClosed event with
DialogResult = DialogResult.OK;
Then you are able to handle the grid reloading in your onclick event like this:
EditFields editFields = new EditFields(programIdInput.Text, fieldIdInput.Text, false);
if (editFields.ShowDialog(this) == DialogResult.OK)
{
RefreshDataGrid();
}
else
{
//it was canceled
}
editFields.Dispose();
You need to pass the main form to the detail form.
In the detail form, implement the OnClosing or OnClosed event and call MainForm.LoadList().

Minimize and Hide Winform on Form Load

I have a Windows Form in a C# program with the FormBorderStyle set to FixedToolWindow.
The window doesn't have the normal control box, but the user can still minimize it from a menu. There is also a setting for the window to start in a minimized state.
When the user clicks the minimize button it called the following function:
private void minimizeWindow()
{
timer1.Enabled = false;
this.WindowState = FormWindowState.Minimized;
this.Hide();
}
The window becomes a small box in the bottom left of the screen, then disappears (from the this.hide call).
When the same function is called from within the Form_Load method (when the setting is to start minimized) it minimizes but does not disappear.
My guess is that because I am hiding the form before reaching the end of Form_Load it is being shown again when it reaches the end of the method. Is there any way to ensure the form hides when it is loaded (it is maximised again from a system tray icon)?
Edit: Included all code from form load
private void Form1_Load(object sender, EventArgs e)
{
this.Left = windowXPos;
this.Top = windowYPos;
sysTrayIcon.MouseDoubleClick += new MouseEventHandler(sysTrayIcon_MouseDoubleClick);
sysTrayIcon.BalloonTipText = "Timers Running";
this.sysTrayIcon.Icon = this.Icon;
sysTrayIcon.Visible = true;
sysTrayIcon.ShowBalloonTip(500);
Start(); //sets up timers
if (startMinimized)
{
minimizeWindow();
}
}
It might be best to change your logic slightly, and instead of showing the form at all, create an instance of it (var foo = new MyForm()) but don't call .Show() so it will never be shown until triggered from your system tray icon.

Why Won't Form Get Focus?

I have a form that is launched modally like this:
private void find_street_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
Form findForm = new FindStreet();
findForm.ShowDialog();
this.WindowState = FormWindowState.Normal;
}
The form launches correctly, and the cursor is in the first text box, whose TabIndex is set to 1.
Along with the InitializeComponent(); call, these commands are present.
public FindStreet()
{
InitializeComponent();
this.TopMost = true;
this.BringToFront();
this.Focus();
}
I have looked at and tried a number of examples. The cursor appears in the correct control, but the form's window does not have the focus. The problem is that if a user starts typing, even though the newly launched form is visible, those keystrokes are not going into the text box.
Remove the code in public FindStreet() and in load event of FindStreet add:
this.TopMost = true; //i don't know why you need this.
this.Activate();
When you minimize your main form the next one in z-order get the cursor. this.Focus() doesn't do anything. You need to Activate the dialog.
A dialog requires an owner, that cannot be a minimized window. Now accidents start to happen, starting with your WindowState assignment. Your app doesn't have a window left that can receive the focus so Windows is forced to find another one, that will be one owned by another application. Same problem happens when you close the dialog.
You can still get the intended effect, you must hide your main window after the dialog is displayed, show it again before the dialog closes. That requires a bit of hackorama:
using (var dlg = FindStreet()) {
// Show main window when dialog is closing
dlg.FormClosing += new FormClosingEventHandler((s, cea) => {
if (!cea.Cancel) this.Show();
});
// Hide main window after dialog is shown
this.BeginInvoke(new Action(() => {
this.Hide();
}));
dlg.StartPosition = FormStartPosition.Manual;
dlg.Location = this.Location;
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
// etc...
}
}
And remove the hacks from the FindStreet constructor. Watch out for event order if you have a FormClosing event handler in FindStreet, be sure to override OnFormClosing() instead.
If you want to set a specific control as the current active control then try this:
this.ActiveControl = myTextBox;
This will place the cursor you want as the main focus, when the form loads. So try this out:
public FindStreet()
{
InitializeComponent();
this.TopMost = true;
this.BringToFront();
this.Focus();
this.ActiveControl = myTextBox;
}
Here is the link to Focus() which should explain why your focus call was not working.

Disable a button and an event if a form is open

I have two forms. The first form get info from the second form doing it this way:
//First Form
if (e.KeyCode == Keys.F4)
{
FormConsultaAdvogado fca = new FormConsultaAdvogado();
fca.MdiParent = this.MdiParent;
fca.Show();
}
Then, in the second form, I choose what I need to get back to the first form with this:
else if (FormClienteAberto())
{
if (e.KeyData == Keys.Enter)
{
FormCliente fdil = (FormCliente)Application.OpenForms["FormCliente"];
fdil.textBox1.Text = dataGridView1.CurrentRow.Cells[0].FormattedValue.ToString();
fdil.textBox2.Text = dataGridView1.CurrentRow.Cells[1].FormattedValue.ToString();
this.Close();
}
}
In the seconde form, I also have a funcion that verifies if the first form is open:
public bool FormClienteAberto()
{
try
{
Form fc = Application.OpenForms["FormCliente"];
return fc != null;
}
catch (Exception)
{
return false;
}
}
So, my problems are:
1st- I have a button in the 2nd form that, when the first form is open, must be hide
2nd- I have a RowHeaderMouseDoubleClick event that i need to disable too, if the first form is already open, too.
Wish that you guys can help me!!
Regards
If you just need to determine those two things when the second form is opened, something like the following in the second form's Load event should work:
if(FormClienteAberto())
{
thatButton.Visible = false;
thatDataGridView.RowHeaderMouseClick -= thatRowHeaderMouseClickEventHandler;
}

Why can I not close a form in C#?

I cannot close one of my forms programmatically. Can someone help me?
Here's the code:
private void WriteCheck_Load(object sender, EventArgs e) {
SelectBankAccountDialog sbad = new SelectBankAccountDialog();
DialogResult result = sbad.ShowDialog();
if (result == DialogResult.Cancel) {
this.Close();
} else {
MessageBox.Show(result.ToString());
}
MessageBox.Show(sbad.bankaccountID.ToString());
}
As configurator mentioned (in comments), the form must be shown before it can be closed, so, instead of the Load event, you should be doing this in the Shown event instead.
If you don't want the form visible for the Dialog box, I guess you can wrap the event code in a Visible = false;
In summary, the basic code would be
private void WriteCheck_Shown(object sender, EventArgs e)
{
Visible = false;
SelectBankAccountDialog sbad = new SelectBankAccountDialog();
DialogResult result = sbad.ShowDialog();
if (result == DialogResult.Cancel) {
this.Close();
} else {
MessageBox.Show(result.ToString());
}
MessageBox.Show(sbad.bankaccountID.ToString());
Visible = true;
}
By calling Form.Close(), the form should close, but not until all waiting events have been processed. You also still have a chance to cancel the form closing in the FormClosing event.
First, you'll probably want to return after your call to this.Close(). If it still doesn't close, step through your code and see what is happening. You may have to set and check a "forciblyClose" flag and return from any other processing methods before it'll actually close.
The actual problem is that windows won't let a form close on it's load method. I have to show the dialog on construction, and then if the dialog result is cancel I have to throw an exception and catch the exception on form creation.
This place talks more about it

Categories