First of all, I want to apologize for:
The software is in Portuguese.
The software is ugly as hell. It is for a school project and we decided to focus more on the funcionality than the design (I know, it's wrong, but we had to choose...)
I read update combobox from another form in c# but I didn't understand what happened.
That said, let's go to the issue.
I have this window:
If I click the button marked in red:
This will open:
This is supposed to be a software for a market. The first window is responsible to order more thing to the inventory. The second window is responsible to add a supplier into the system.
The combobox shows all the suppliers on the system. I want when I finish adding a supplier on the second window after I clicked on the button highlighted with the red rectangle, the combobox will update automatically with the new data.
I used a "Update" button with this code:
this.tb_FornecedorTableAdapter.Fill(this.tccDataSet.tb_Fornecedor);
It worked, but I tried to use on FormClosing, FormClosed and Deactivate events on the other windows and it didn't work at all (I modified the "this" on the code to a lot of this and it didn't help me). Is there a way to do what I want?
If the ComboBox is updated with the data from SQL Server then you can try this:
// When button Adicionar is clicked
private void buttonAdd_Click(object sender, EventArgs e)
{
using(Form formAdd = new Form()) // This is the Gerenciar Fornecedor form
{
formAdd.ShowDialog(this); // Show the form. The next statement will not be executed until formAdd is closed
// Put the your code to update the ComboBox items here
}
}
In the first window declare a public methord:
public void RefreshCombo()
{
this.tb_FornecedorTableAdapter.Fill(this.tccDataSet.tb_Fornecedor);
}
Then in the first window add button click event
WindowB window=new WindowB(this);
WindowB.Show();
Then in the child window add a ctor method:
private WindowA windowParent;
public WindowB(WindowA parent)
{
InitializeComponent();
this.windowParent=parent;
}
In WindowB FormClosing Event
this.windowParent.RefreshCombo()
What you can do in this case is to add a property on the child form to store the combo box value and populate it when the combo box value changes. Also, create a method on the child form that will be called from the parent form. It will show the child form and return the combo box value.
public partial class ChildForm : Form
{
public ChildForm()
{
InitializeComponent();
}
private string _comboValue { get; set; }
public string ShowAndGetComboValue()
{
this.ShowDialog();
return _comboValue;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
_comboValue = comboBox1.SelectedItem.ToString();
}
}
On the parent form, you can then display the child form this way:
ChildForm form = new ChildForm();
string comboValue = form.ShowAndGetComboValue();
Related
I am working on a WinForms Desktop application in C# .NET. The target framework is .NET Framework 4.8. When the application is started, the main form is displayed with several buttons. Each button hides the main form when clicked and opens another form that displays data with which the user interacts. The main form is the owner of the new form.One button opens a form that presents a list of files from a network share folder in a data grid view. The user selects a row in the data grid and clicks a button to import the information in the file to various tables in a SQL Server database. When the import is complete, the selected row is removed from the data grid. When the user closes this form, there is code in the Form Closed event to show the owner. This all works well.My problem is that when the main form is unhidden, I need to disable the button that opens the form to list files to import if there are not any files in the network share folder to be imported. There is also a line of code to change the button's text property informing the user there are not any files to import.I realize I can place the code to disable the button and change button text in the VisibleChanged event. But, I only want the code to run after the owned form's closed event shows the owner form. How do I enclose the code in the main form's VisibleChanged event to disable the file import button only after the owned form is closed. Or, is it possible to edit the properties of the button on the owner form in the Form Closed event prior to the Owner.Show();I found a similar question WinForm Form Closed Event. But when I follow the suggestion
private void LoadChildForm_Click(object sender, EventArgs e)
{
ChildForm form = new ChildForm();
form.FormClosed += new FormClosedEventHandler(ChildFormClosed);
form.Show();
}
substituting my names
private void btnImportHFR_Click(object sender, EventArgs e)
{
Form form = new frmHFRFiles();
form.FormClosed += new FormClosedEventHandler(frmHFRFiles_FormClosed);
form.Show(this);
Hide();
}
Visual Studio flags frmHFRFiles_FormClosed as an error for the name does not exist in the current context.
ChildForm form = new ChildForm(this);
Then in ChildForm constructor:
MainForm m_MainForm;
Public ChildForm (MainForm mainForm)
{
m_MainForm = mainForm;
}
Then in closing event:
m_MainForm.button1.Enabled = false;
Ensure button1 is public
Here is what I did. I created a boolean variable in the main form and set the initial value to false.
private bool updateButtons = false;
The main form's constructor executes the search for files in the network folder.
public frmMainMenu()
{
InitializeComponent();
Shared.FilesForImport = GetHFRFiles();
}
The form's load event calls the EnableButtons() method
public void EnableButtons()
{
btnImportHFR.Enabled = Convert.ToBoolean(Shared.FilesForImport.Count);
btnImportHFR.Text = btnImportHFR.Enabled ? "Find Available HFR" : "No HFR For Import";
btnGetFacilityStatus.Enabled = Shared.sqlWrap.GetDataForFacStat(Shared.DsFacStat);
updateButtons = false;
}
The main form's visible changed event fires after the form load event. The network folder is not searched again because the updateButtons value is set to false.
private void frmMainMenu_VisibleChanged(object sender, EventArgs e)
{
if(updateButtons)
{
EnableButtons();
}
}
In the button click event, the updateButtons value is set to true after the main form is hidden.
private void btnImportHFR_Click(object sender, EventArgs e)
{
frmHFRFiles form = new frmHFRFiles();
form.Show(this);
Hide();
updateButtons = true;
}
The child form's closed event calls the Owner.Show() method
private void frmHFRFiles_FormClosed(object sender, FormClosedEventArgs e)
{
Owner.Show();
}
This causes the main form's visible changed event to fire. Only this time the EnableButtons() method will run because the updateButtons value is true.
private void frmMainMenu_VisibleChanged(object sender, EventArgs e)
{
if(updateButtons)
{
EnableButtons();
}
}
public void EnableButtons()
{
btnImportHFR.Enabled = Convert.ToBoolean(Shared.FilesForImport.Count);
btnImportHFR.Text = btnImportHFR.Enabled ? "Find Available HFR" : "No HFR For Import";
btnGetFacilityStatus.Enabled = Shared.sqlWrap.GetDataForFacStat(Shared.DsFacStat);
updateButtons = false;
}
Finally, the EnableButtons() method sets the updateButtons value to false.
It seems rudimentary to me, but it works. Thank you everyone for your feedback.
My problem is that when the main form is unhidden, I need to disable the button that opens the form to list files to import if there are not any files in the network share folder to be imported. There is also a line of code to change the button's text property informing the user there are not any files to import.
So your main form has a button X. If this button is clicked a method is called. This method will first hide the form, then show the subform until the subform is closed. The method should disable button X, change the button's text and unhide the form.
To make this flexible, we won't do everything in one procedure, we make several procedures with the intention of the procedure: "Inform operator there are no files to import" "Disable opening the subform", and of course their counterparts "Enable opening the subform", "Inform operator there are files to import"
TODO: invent proper method names
private void ShowNoFilesToImport()
{
this.buttonX.Text = ...;
}
private void DisableOpeningSubForm()
{
this.buttonX.Text.Enabled = false;
}
The advantage of this, is that if you later want to change the way that you want to inform the operator, for instance if you want to use an information field at the bottom of you screen, you will only have to change this in one place.
Furthermore, you can reuse the procedures, for instance you can add a menu item that will do the same as button X, this menu item can call the same methods
private void PerformActionsButtonX() // TODO: invent proper name
{
// Hide this form, and show the Subform until it is closed
this.Visible = false;
using (var dlg = new SubForm())
{
// if needed, set properties of the subForm:
dlg.Text = ...
dlg.Position = ...
// show the form until it is closed
var dlgResult = dlg.ShowDialog();
this.ProcessDlgResult(dlgResult, dlg);
}
// Show that there are no files to Import and disable OpeningSubform
this.ShowNoFilesToImport();
this.DisableOpeningSubform();
// Finally: show this form:
this.Visible = true;
}
And of course call this method when ButtonX or menu item Y are clicked:
private void OnButtonX_Clicked(object sender, ...)
{
this.PerformActionsButtonX();
}
private void OnMenyItemYClicked(object sender, ...)
{
this.PerformActionsButtonX();
}
I have two forms.
1st one is frmStudentDetails. It has a datagrid
2nd one is frmStudentRegistration. It has some text boxes and Add button
When user enter some information and press "Add" button, I want to add those to the datagrid one by one
For accomplish that 1st I created following method in frmStudentDetails
public void AddRecord(string StID, string Name)
{
DataGridViewRow row = (DataGridViewRow)dgvStDetails.Rows[0].Clone();
row.Cells[0].Value = StID;
row.Cells[1].Value = Name;
dgvStDetails.Rows.Add(row);
}
I called it on frmStudentRegistration form's add button -->
private void btnAdd_Click(object sender, EventArgs e)
{
frmStudentDetailsForm frm = new frmStudentDetailsForm();
frm.AddRecord(txtStudentID.Text, txtStName.Text);
frm.ShowDialog();
}
Then the problem is, itz generating new forms to show every new record.
But i want to add all records in one form.
please somebody help me for that
In your "frmStudentRegistration" Class, add a "public frmStudentDetailsForm StudentDetailsForm { get; set; };" Property Declaration at the Class level.
Set it equal to the Instance of your "frmStudentDetailsForm" Class. There are several ways you can do so (i.e. in "frmStudentRegistration" Class's custom Constructor or its "Load" Event Handler), but for a novice, I would recommend just setting it after you Instantiate your "frmStudentRegistration" Class and before you call that Instance Variable's "Show" Method. NOTE: If you call "frmStudentRegistration"'s "ShowDialog" Method, any updates to other Forms (i.e. "frmStudentDetailsForm") won't show on screen until you exit "ShowDialog" or you explicity call the other Form's "Show" or "ShowDialog" Methods.
On a side note, I'm curious as to why you're calling "frmStudentDetailsForm"'s "ShowDialog" Method from "frmStudentRegistration". In my experience, either: a) the grid's Form would call "ShowDialog" on the add-item's Form with the "Add" option (i.e. via Button, Context Menu item, Insert Key and/or Enter Key (after filling in a new template Row)) being on the grid's Form or b) both Forms would remain open at the same time (via Modeless "Show" Method Calls) with the "Add" option on the add-item's form. Btw, in my experience your "frmStudentRegistration" Form would be called the "frmStudentDetailsForm" and your "frmStudentDetailsForm" would be called something like "frmStudentsForm", "frmStudentsListForm" or "frmStudentSummariesForm", etc. Also, btw, the .NET naming convention would be "var studentDetailsForm = new StudentDetailsForm()" (i.e. suffix vs. prefix/both and no abbrev.). Actually, if were up to me, it would be "var StudentDetailsFrmObj = new StudentDetailsFrmCls()". ;)
Ex.
In "frmStudentRegistration":
public frmStudentDetailsForm StudentDetailsForm { get; set; }
public void main ()
{
var studentRegistration = new frmStudentRegistration();
var studentDetailsForm = new frmStudentDetailsForm();
studentRegistration.StudentDetailsForm = studentDetailsForm;
studentRegistration.Show();
}
In "frmStudentRegistration":
private void btnAdd_Click(object sender, EventArgs e)
{
StudentDetailsForm.AddRecord(txtStudentID.Text, txtStName.Text);
StudentDetailsForm.ShowDialog();
}
I created a new Event in my user control (SearchControl) like this:
//Event which is triggered on double click or Enter
public event EditRecordEventHandler EditRecord;
public delegate void EditRecordEventHandler(object sender, EventArgs e);
//Supressing the events
private bool _raiseEvents = true;
private void OnEditRecord(System.EventArgs e)
{
if (_raiseEvents)
{
if (this.SearchResultGridView.FocusedRowHandle > -1)
{
if (EditRecord != null)
{
EditRecord(this, e);
}
}
}
}
Now this Event is called when user double click a row in a grid. So from the properties window I selected the MouseDoubleClick Event of the grid view and called the above created EditRecord event.
private void SearchResultListGridControl_MouseDoubleClick(object sender, MouseEventArgs e)
{
// Check whether the user clicked on a real and not a header row or group row
DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitInfo info = SearchResultGridView.CalcHitInfo(e.Location);
if (info.InRow && !SearchResultGridView.IsGroupRow(info.RowHandle))
{
OnEditRecord(e);
}
}
Now the issue I am facing is every time I double click a row in grid view it calls the SearchResultListGridControl_MouseDoubleClick() which then calls OnEditRecord(), however the value of EditRecord is everytime null.
To solve this I checked the designer file of the Main Control which has SearchControl and could not find the EditRecord Event entry in this. So I manually created it like this:
this.MySearchControl.EditRecord += new performis.BA.Merkmalsleisten.Search.SearchControl.EditRecordEventHandle(this.MySearchControl_EditRecord);
Now the things are working fine, but my question is why it did not create it automatically at the first place? And as far I know it is not recommendable to add anything manually to the designer file..is there any other way I can do it?
Thanks
When you create event it has to be used in the form designer similar to how you are using MouseDoubleClick for the Grid (so you need to find event in the Misc category, because you didn't define CategoryAttribute, double clicked there, etc).
If I understand it right you want to subscribe to event automatically, when form is created. You can do this in the control constructor (find parent form control.Parent or control.FindForm()) or perhaps in the special method, which you have to call from the form constructor, which in turn is basically similar to wiring event manually (which you did in the designer created file, but, instead, you can do in the form file, which is totally ok to edit) Up to you.
Sure.
A better practice would be to add your binding line:
this.MySearchControl.EditRecord += new performis.BA.Merkmalsleisten.Search.SearchControl.EditRecordEventHandle(this.MySearchControl_EditRecord);
To the form's constructor. something like:
public MyForm()
{
this.MySearchControl.EditRecord += new performis.BA.Merkmalsleisten.Search.SearchControl.EditRecordEventHandle(this.MySearchControl_EditRecord);
//The rest of your constructor.
}
I have the following situation: The main window where some of the data is completed, it is also a button that opens a new modal window where you choose the product and the range of products, I click OK and move on to the next screen where choose the quantity, price, and after approval of the data which I click OK, I want to have access to the data selected in modal windows in the main window, as it can be done using C #?
You can do something that looks more or less like this:
private void button1_Click(object sender, EventArgs e)
{
Form2 firstPopup = new Form2();
firstPopup.ShowDialog();
var someData = firstPopup.SomeValue;
Form2 secondPopup = new Form2();
secondPopup.ShowDialog();
var someOtherData = secondPopup.SomeValue;
doSomeStuff(someData, someOtherData);
}
In this case SomeValue is a property on the form with a public getter and a private setter. It's value will be set sometime before the form is closed. You can have any number of such properties per form, and any number of forms.
This is similar to the way that Open, Save As and Folder dialogs work. Take for example the Open File Dialog, once you click OK, you have access to the file that was selected
Suggestion:
In your modal window, set some public properties which hold your data. Set your OK button to set the forms DialogResult to OK, in your parent form you can do the following test (in this instance, DataModel is the data you are trying to access)
if(modalWindow.DialogResult == DialogResult.OK)
{
this.DataModel = modalWindow.DataModel;
}
Here is some information on how to use DialogResult
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.dialogresult.aspx
Typically with a Modal window you follow a similar pattern to that used by the OpenFileDialog, where you do something like this:
public class MyDialog : Form
{
public MyResult Result { get { /* code elided */ } }
}
I.e, in addition to having the modal form's code - you also expose a public Result property of a given type which can provide the data entered on that form's UI (this is better than exposing the controls on the form as it means you are free to change all of that without having to re-code any other forms that depends on it).
You make sure that the Result is guaranteed to be available and valid if the Ok or Yes (whatever the confirmation button is) button is clicked. Then you make sure that you set the DialogResult of the form accordingly (you can assign one to each button as well - e.g. DialogResult.Cancel to a cancel button).
Then when you open your form you do it something like this:
var form1 = new MyDialog();
if(form1.ShowDialog() != DialogResult.OK)
return; //abort the operation, the user cancelled/closed the first modal
MyResult form1Data = form1.Result; //get your actual data from that modal form.
//...and then on with your second modal
So you collect the data from the modal(s) as you go along, aborting if any are cancelled.
Try not using a modal window!
If you call
var dialog = new DialogWindow();
If (dialog.ShowDialog(mainWindow) == DialogResult.OK) {
use the result of the dialog window
}
the dialog window will be modal, which means that you cannot access other windows while it is open.
With the following code, both windows are accessible at the same time. The problem is, however, that the code in the main window is not paused while the dialog runs.
var dialog = new DialogWindow();
dialog.Show(mainWindow);
You cannot use the result of the dialog window here!
Therefore you need a way to communicate the completion of the dialog to the main window. I suggest creating an event in the dialog window for this purpose
public class ProductResultEventArgs : EventArgs
{
public ProductResultEventArgs(List<Product> products)
{
Products = products;
}
public List<Product> Products { get; private set; }
}
In the dialog window
public event EventHandler<ProductResultEventArgs> ProductsChosen;
private void OnProductsChosen(List<Product> products)
{
var eh = ProductsChosen;
if (eh != null) {
eh(this, new ProductResultEventArgs(products));
}
}
private BtnOk_Click(object sender, EventArgs e)
{
OnProductsChosen(somehow get the product list);
}
In the main window you can do something like this
var dialog = new DialogWindow();
dialog.ProcuctsChosen += Dialog_ProductsChosen
dialog.Show(mainWindow);
and create a handler
private Dialog_ProductsChosen(object sender, ProductResultEventArgs e)
{
use e.Products here
}
Note: Passing the main window as parameter to ShowDialog or Show makes the main window owner of the dialog. This means that the dialog window will always stay in front of the main window and cannot disappear behind it. If you minimize the main window, this will minimize the dialog window as well.
I have a Main page that contains a listBox.
When a user selects a profile form the list box, this opens up a child window called pWindow.
This window as the option to delete the current profile via a hyperlink button that opens up a another confirmation window called dprofile.
My question being is it possible that once a user has confirmed to delete the current profile they are in, and confirmed it in the button click on dProfile, how can I update the listBox in the first Main page so that the list no longer contains the deleted profile (which it is not doing at present.
In the dProfile window I have created an event -
public event EventHandler SubmitClicked;
Where in the OK button click I have-
private void OKButton_Click(object sender, RoutedEventArgs e)
{
if (SubmitClicked != null)
{
SubmitClicked(this, new EventArgs());
}
}
So on the Main page I have added-
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
WebService.Service1SoapClient client = new WebService.Service1SoapClient();
listBox1.Items.Clear();
client.profileListCompleted += new EventHandler<profileListCompletedEventArgs>(client_profileListCompleted);
client.profileListAsync(ID);
}
I thought this may have updated the listBox as it was confirmed in the dProfile form however when the form closes, the listBox stays the same and I have to manually refresh the webpage to see the update. How can I do this?
If I understood it correctly then you have three pages. Main, pWindow and dProfile. Earlier you were trying to close pWindwow from dProfile and that was working properly. Now you want to refresh the listBox1 on Main Page.
To achieve that you may follow a similar strategy. You are probably opening pWindow from Main page with something on the following line
pWindow pWin = new pWindow();
pWin.Show();
Now you may define a new event in pWindow class.
public event EventHandler pWindowRefeshListBox;
Then in your event handler for deleteProfile_SubmitClicked you may raise the event to refresh listbox1, something on the following line:
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
if(pWindowRefreshListBox != null)
pWindowRefreshListBox(this, new EventArgs());
this.Close();
}
Then in your main page register the event against pWin object, which you defined earlier.
pWin.pWindowRefreshListBox += new new EventHandler(pWindow_pWindowRefreshListBox);
Then define the event in Main page.
private void pWindow_pWindowRefreshListBox(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
This should refresh the listbox. I haven't test the code or the syntax. So you may check it
before implementing.
EDIT
you may define the event in dProfile as static
public static event EventHandler SubmitClicked;
Then you will be able to register it in Main and pWindow against Class Name
dProfile.SubmitClicked += new ..............
Then implement it accordingly, in pWindow, close the window and in main refresh listbox
EDIT:
You may create instance of deleteProfile on the main page register the following in your main
deleteProfile.SubmitClicked += new EventHandler(deleteProfile _SubmitClicked)
this should work