I have a dictionary list of forms which are Documents within DockPanelSuite (Windows Forms) When a button on the main form is pressed all the document's "Contents" contained in the first control (ScintillaNet Editor instance) of the Document Form should be saved.
However, accessing the Save() method of the form is proving frustrating.
Currently this is the code:
private void btnCompile_Click(object sender, EventArgs e)
{
// Save the Project.
foreach(var editor in EditorList)
{
if(editor.Key.StartsWith(CurrentProjectModel.Name))
{
FrmCodeEditor fce = new FrmCodeEditor();
fce = (FrmCodeEditor)editor.Value;
fce.Save();
}
}
IDA.Controllers.CLI.Exec exec = new Controllers.CLI.Exec();
exec.ExecuteCompiler();
}
editor is the name of the form, EditorList is the Dictionary which contains a list of all active Documents. However, the fce.Save is not being found.
Question
All I want to do is iterate through all the open Documents which are FrmEditor types and call their Save method. How can I do that?
As it turned out - the method I was trying to call was static. However, this was not being flagged in intellisense.
Related
I have a Windows Forms App in C# with multiple UserControls.
In the UserControl1 I create panels dynamically, each panel containing multiple elements (checkbox, label listbox, picturebox, and multiple comboboxes). The values inside these elements differs between panels because I import the values from a Database. Also, I can add or remove elements from the listbox. Basically each panel is a presentation for a Pizza menu where you select the size (each size has its own price) and add or remove ingredients (from the listbox).
If you select one (or more) of the pizza's it is added in the UserControl2 (designated as a shopping cart). You can select multiple (different) pizza items from the UserControl1, and all of them will appear in the UserControl2 in the "shopping cart".
All these UserControls are contained in a panel in a Form and can be accessed by clicking a corresponding button.
My question is, how do I reload the UserControl1 from UserControl2?
Basically, after I'm done making an "order" (which can have multiple different items), I want to make a new "order" and I want the UserControl1 to look just like it was when I started the app.
I realize that I have to call the UserControl1_Load() method, but how do I do that from the UserControl2?
Or is there another method of "resetting" the UserControl1?
Obviously, I'm kind of new to C# so, please, have mercy on my soul.
Thank you very much in advance for your help!
I would implement an interface which each UserControl should implement to support this feature. The interface is a contract describing that the control has implemented a method. Just try to cast all usercontrols to that interface to support the restart functionality.
You should change it for your needs, but here is an example:
public interface ISupportInitialize
{
void Initialize();
}
public partial class MyUserControl : UserControl, ISupportInitialize
{
public MyUserControl()
{
// whatever you need to initialize
Initialize();
}
public void Initialize()
{
// remove old content if exists
// add new content
}
}
And in your main window:
public void ReInitializeControls()
{
// assume that panel1 contains the controls.
var userControlsWithInitialize = panel1.Controls.OfType<ISupportInitialize>();
foreach(var control in userControlsWithInitialize)
control.Initialize();
}
Calling the Load() method may not be sufficient. If you want a total reset behavior, you can remove the current control and add a brand new one in place of it.
Assuming you know how to implement an event handler, this goes inside the user control which triggers the reset operation, as a member variable:
public EventHandler OnOrderCompleted;
And when the order is completed, the control should invoke:
private void button1_Click(object sender, EventArgs e)
{
if (OnOrderCompleted != null)
{
OnOrderCompleted.Invoke(this, new EventArgs());
}
}
To keep coupling at minimum, this control should not directly know about the user control to be reset, but should inform any observers about the completion of an order. In our case, this can be the form hosting all the controls: (We name the triggering control orderControl here)
public Form2()
{
InitializeComponent();
orderControl.OnOrderCompleted += OnOrderCompleted;
}
private void OnOrderCompleted(object sender, EventArgs e)
{
Point currentLocation = productsControl.Location;
Controls.Remove(productsControl);
productsControl = new UserControl1();
productsControl.Location = currentLocation;
Controls.Add(productsControl);
}
Hope this helps.
Just a quick one!
I've had to add a second form to my windows form application due to not physically having the space for more textboxes.
Some of the textboxes have ended up being the same as on the original form (I know this isn't ideal, but the two forms each write to separate text files, so it works out easier overall)
With this being the case, I'd like the values in the textboxes from the original form to be copied into their duplicate textboxes on the second form (trying to prevent double data entry and reduce risk of errors).
So, I have a button click on the first (Form1) form that calls the .Show() function to load a new version of the second form (PreAnaestheticChecklist).
public void btnPreOpChecklist_Click(object sender, EventArgs e)
{
//create secondary form for pre-anaesthetic checklist
PreAnaestheticChecklist checklistForm = new PreAnaestheticChecklist();
//load pre-anaesthetic checklist form to screen
checklistForm.Show();
}
This works fine, and the form loads up as blank. I wrote a load of small string functions that return strings that are comprised of the text in the textboxes from form1. These are called in the PreAnaestheticChecklist_Load event. An example is shown below using one of the transfers as an example.
public string getProcedure()
{
//load value from textbox in IOconsole
string proc = main.txtProcedure.Text;
//return this to textbox on Checklist
return proc;
}
public void PreAnaestheticChecklist_Load(object sender, EventArgs e)
{
//load any values already on main form into respective textboxes
txtProcName.Text = getProcedure();
txtPlannedProc.Text = getProcedure();
}
This is done for another few textboxes, but even with all this, the second form loads as blank.
I read up and was advised to try putting all of the textbox assignments from the _Load event into the button click event that loads form2, and still nothing.
I also changed the Modifiers property for all forms envolved to 'Public', and still nothing!
Not sure where to look next, so any help with the matter is very much appreciated!
Thanks in advance,
Mark
Pass in Form1 as the Owner when you call Show():
public void btnPreOpChecklist_Click(object sender, EventArgs e)
{
//create secondary form for pre-anaesthetic checklist
PreAnaestheticChecklist checklistForm = new PreAnaestheticChecklist();
//load pre-anaesthetic checklist form to screen
checklistForm.Show(this); // <-- passing in the Owner
}
Now, in the Load() event of your PreAnaestheticChecklist Form, cast the .Owner property to Form1 and store it in your "main" variable:
public void PreAnaestheticChecklist_Load(object sender, EventArgs e)
{
this.main = (Form1)this.Owner;
//load any values already on main form into respective textboxes
txtProcName.Text = getProcedure();
txtPlannedProc.Text = getProcedure();
}
I have a problem with not being able to refresh my form that has a DataGridView.
I open a form called MaintenanceForm.
Here I will choose a car, give the amount of km, and the option to add products.
If I click on the add products button, this form will stay open while another will open as well called AddProducts. In this form I will choose from a list of products that I will add to my final listbox. If I click Save, these items will go to my BindingList and populate my grid.
I have tested this with closing my first form first and reopening it with my second form. The grid was populated.
How do I populate my grid without having to close my first form?
Here are the methods I'm using
Save button on my second form:
private void btnOpslaan_Click(object sender, EventArgs e)
{
lstTotal = new BindingList<Product>();
foreach (object product in listBtotal.Items)
{
lstTotal.Add((Product)product);
}
MaintenanceForm maintenanceForm = new MaintenanceForm();
maintenanceForm.FillDataGridView(lstTotal);
this.Close();
}
Method to populate my grid:
public void FillDataGridView(BindingList<Product> products)
{
dGvProducts.DataSource = null;
dGvProducts.AutoGenerateColumns = false;
dGvProducts.AllowUserToAddRows = false;
dGvProducts.DataSource = products;
dGvProducts.Refresh();
}
Again the MaintenanceForm is still open while AddProductsForm is open?
Thanks in advance
Thanks to the user JDB i have fixed my problem.
Instead of making a new instance (Thank you Junaith for correcting me for it) I'm now making a LogicalParent method.
public AdminForm LogicalParent { get; set; }
With this i have access to al methods and functions of my parent Form and no problems with refreshing.
I currently have a class that handles my treeview and other winForm components.
I want to use another form which act as my input and once I press the save button it should update my treeview component on the other form. So far what I tried has not worked.
here is my code:
*mainDisplay is my form which includes my component and stores my variable that holds the data
Here I load my date into the treeview
public void mainDisplay_Load( TreeNode input)
{
treeView1.BeginUpdate();
foreach (data x in mydata1)
{
Console.WriteLine(x.getName());
if (x.getName() != null)
{
treeView1.Nodes.Add(input);
}
}
treeView1.Refresh();
}
here is my button action on the OTHER form:
private void button1_Click(object sender, EventArgs e)
{
if (!(String.IsNullOrEmpty(getnamebox.Text))) ;
{
mainDisplay putdata = new mainDisplay();
name = getnamebox.Text;
pass = getpassbox.Text;
url = geturlbox.Text;
notes = getnotebox.Text;
data newData = new data(name, pass, notes);
mainDisplay.mydata1.Add(newData);
TreeNode mytree = new TreeNode(name);
putdata.mainDisplay_Load(mytree);
this.Hide();
}
Any tip would be appreciated.
You just created a brand new main display form somewhere (in memory) and added a tree node to it.
You need to pass the reference of your main display forward (usually in an initialize function or trace back your second form's parentage depending on how your stuff was set up) and then use the reference to your actual main form to update the tree.
I currently have a parent control (Form1) and a child control (Form2).
Form1 contains a listview that stores a list of of file data (each file is a separate item).
Form2 contains only a textbox.
Upon clicking on one of these listviewitems in Form1, Form2 is opened up and accesses the file's data and loads it into the textbox in Form2 in plain text format.
The issue I'm having is, I would like to be able to detect, upon clicking of a listviewitem, whether that file is already opened in said child form and if so, to activate it (bring it to the front) and if it is not already opened, open it. I'm not sure what the best method of doing this would be since this can involve many child forms being open at once. This is not an MDI application. Any ideas on how this could be accomplished are appreciated and samples even more so. Thank you.
What I have done in the past is give each new form a unique tag (based on the file you're viewing in this case), so:
var form = new Form2();
form.Tag = (object)"My Unique Object as a Tag"; // Redundant cast I know, but shows Tag is of type object
Then, when going to open up a window for a file, iterate over all the open forms checking tags like so:
foreach(var f in Application.OpenForms)
{
if(f.Tag == tagForFile)
{
f.BringToFront();
return;
}
}
// Couldn't find one, so open on
var form = new Form2();
form.Tag = tagForFile;
form.Show();
And this should only open up one form per file (or tag really)
Hopefully that helps !
You could simply maintain a Dictionary<ListViewItem,Form>. Each time you open a new form add an entry to the dictionary. If the dictionary already contains the ListViewItem that was clicked as a key then you don't need to open a new form.
Assuming form is created for every selected item you could keep track of opened forms in ListViewItem's tag.
lv.ItemSelectionChanged += lv_ItemSelectionChanged;
private void lv_ItemSelectionChanged(Object sender, ListViewItemSelectionChangedEventArgs e)
{
if(e.IsSelected)
{
if(e.Item.Tag == null)
{
var form = new Form2();
// init Form2 here
form.Parent = this.panel1;
e.Item.Tag = form;
}
(e.Item as Form2).BringToFront();
}
}
EDIT:
On the other hand why would you create and switch between forms which have only one Edit, it would be much simpler to just fill TextBox with file contents:
ListView1.ItemActivate += ListView1_ItemActivate;
private void ListView1_ItemActivate(Object sender, EventArgs e)
{
if(ListView1.SelectedItems.Count > 0)
{
this.form2Instance.ContentsTextBox.Text = File.ReadAllText(this.rootFilesPath + #"\" + ListView1.SelectedItems.Last().Text));
}
}
And if you wamt to read file contents only once, just save file contents in ListViewItem's tag
ListView1.ItemActivate += ListView1_ItemActivate;
private void ListView1_ItemActivate(Object sender, EventArgs e)
{
if(ListView1.SelectedItems.Count > 0)
{
var item = ListView1.SelectedItems.Last();
if(item.Tag == null)
item.Tag = File.ReadAllText(this.rootFilesPath + #"\" + item.Text);
this.form2Instance.ContentsTextBox.Text = (string) item.Tag;
}
}