I have a user control that I can drag and drop in the Form1.cs[Design] mode. The designer will auto-generate code for this user control in the Form1.Designer.cs
What I would like to get aswell is: at the moment I am adding the user control to the form by dragging I wont to have code generated in my Form.cs that is pointing to the properties and controls on that user control.
Example of user control:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string TextInTextBox
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
}
So now when I drag it on the form in the Form1.cs[Design]. I won't part of code like this to be generated in my Form1.cs:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
AddText();
}
// this code below to be auto-generated
private void AddText()
{
userControl11.TextInTextBox = "";
}
}
I think I should be looking for something like inheritance or interface but I would like this to happen for each instance of that user control.
If someone could point me direction what to look for it would be great. Thanks.
Usually you don't need to generate code manually when you want to assign a property when dropping a control from toolbox, for example you can easily do this:
public MyUserControl()
{
InitializeComponent();
MyTextProperty = "Something";
}
And it will be serialized automatically.
But there are more options for more advanced requirements.if you know the options that you have, you may choose based on your requirement. Here is some options:
Assign some value in constructor or to the property
Assign value to properties using ToolboxItem, it will overwrite the value which you assign in constructor.
Generate some code for Load event of form and initialize property there. It's useful for complex code generations, for example when you drop a data source it will generate some code to load data and add to load event of form.
Assuming you have assigned Something to MyTextProperty in constructor, then when you drop the control in form, here is what will be generated in designer.cs:
this.myUserControl1.MyTextProperty = "Something";
If you use the ToolboxItem solution to assign Something else to the property, the result in designer.cs file will be:
this.myUserControl1.MyTextProperty = "Something else";
And if you decide to use third option and generate event handler code, the result in designer.cs file will be:
this.Load += new System.EventHandler(this.Form1_Load);
and the result in cs file will be:
private void Form1_Load(object sender, EventArgs e)
{
myUserControl1.MyTextProperty = "Even something else!";
}
Example
Here is a full code of MyUserControl, MyUserControlToolboxItem and MyUserControlDesigner. You can comment Designer and/or ToolboxItem attributes and close all designers and clean and rebuild the solution and drop an instance of the control on the form to see how it works.
using System.CodeDom;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Forms.Design;
[Designer(typeof(MyUserControlDesigner))]
[ToolboxItem(typeof(MyUserControlToolBoxItem))]
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public string MyTextProperty { get; set; } = "Something";
}
public class MyUserControlToolBoxItem : ToolboxItem
{
protected override IComponent[] CreateComponentsCore(IDesignerHost host)
{
IComponent[] componentsCore = base.CreateComponentsCore(host);
if (componentsCore != null && componentsCore.Length > 0
&& componentsCore[0] is MyUserControl)
(componentsCore[0] as MyUserControl)
.MyTextProperty = "Something else"; ;
return componentsCore;
}
}
public class MyUserControlDesigner : ControlDesigner
{
public override void InitializeNewComponent(IDictionary defaultValues)
{
base.InitializeNewComponent(defaultValues);
var component = Control;
var eventBindingService = (IEventBindingService)this.GetService(
typeof(IEventBindingService));
var componentChangeService = (IComponentChangeService)this.GetService(
typeof(IComponentChangeService));
var designerHostService = (IDesignerHost)GetService(typeof(IDesignerHost));
var rootComponent = designerHostService.RootComponent;
var uiService = (IUIService)GetService(typeof(IUIService));
var designerTransaction = (DesignerTransaction)null;
try
{
designerTransaction = designerHostService.CreateTransaction();
var e = TypeDescriptor.GetEvents(rootComponent)["Load"];
if (e != null)
{
var methodName = "";
var eventProperty = eventBindingService.GetEventProperty(e);
if (eventProperty.GetValue(rootComponent) == null)
{
methodName = eventBindingService
.CreateUniqueMethodName(rootComponent, e);
eventProperty.SetValue(rootComponent, methodName);
}
else
methodName = (string)eventProperty.GetValue(rootComponent);
var code = this.GetService(typeof(CodeTypeDeclaration))
as CodeTypeDeclaration;
CodeMemberMethod method = null;
var member = code.Members.Cast<CodeTypeMember>()
.Where(x => x.Name == methodName).FirstOrDefault();
if (member != null)
{
method = (CodeMemberMethod)member;
method.Statements.Add(
new CodeSnippetStatement($"{Control.Name}" +
$".MyTextProperty = \"Even something else!\";"));
}
componentChangeService.OnComponentChanged(rootComponent,
eventProperty, null, null);
eventBindingService.ShowCode(rootComponent, e);
}
designerTransaction.Commit();
}
catch (System.Exception ex)
{
if (designerTransaction != null)
designerTransaction.Cancel();
uiService.ShowError(ex);
}
}
}
i been trying to link constructors but i been having issues as i have a lot of different classes witch share a lot of info with each other as so as it stands currently this is what i want to do
get one of the classes to reverence form1 so i can run a certain method
so this is what i have tryied so far
gscadding.cs
public SoundAlis sounds;
public addingweapons dlc3gsc;
public Form1 elfgsc;
public gscadding elfy;
private gscadding elfy1;
public gscadding(addingweapons dlc3)
{
dlc3gsc = dlc3;
}
public gscadding(gscadding elfy1)
{
// TODO: Complete member initialization
this.elfy1 = elfy1;
}
this is the class i want to get into form one to use a function i made in form 1
this is what i have in form1
elfenlied_program_settings elf;
addingweapons elf_weap;
Parser elfenliedl;
gscadding elfy;
//Parser parser = new Parser("model1887_sp");
public Form1()
{
InitializeComponent();
updater1.CheckForUpdates();
listBoxAdv1.Visible = false;
elf = new elfenlied_program_settings(listBoxAdv1,elfenliedl);
elf_weap = new addingweapons(richTextBoxEx1);
elfenliedl = new Parser("model1887_sp");
elfy = new gscadding(elfy);
timer1.Start();
elf.buttonX2 = buttonX2;
elf.elfenform = this;
// elfe.elfgsc = this;
buttonX2.Visible = false;
buttonX3.Enabled = true;
textBoxX6.Enabled = false;
elfenliedl.buttonX1 = buttonX1;
basicly what im trying to do is form gscadding.cs to call a function called updatesettings();
witch when the form loads and i select a path it updates all string = paths
but i keep getting the
elfgsc is null you have to set it.
public gscadding(addingweapons dlc3, Form1 form)
{
dlc3gsc = dlc3;
elfgsc = form;
}
In your form constructor
elfy = new gscadding(elfy, this);
Now you can call methods in your form from your gscadding class like so:
elfgsc.updatesettings();
As to your second error, passing elfy to itself is useless. Remove elfy and replace with elfy_weap
I have a windows forms application with some controls added to the designer. When I want to change something (LIKE) enabling a text box from inside the Form1.cs, I simply use:
textBox1.Enabled = true;
but now I have a separated class called class1.cs.
How could I enable textBox1 from a static function class1.cs?
NOTE: I did not try any code because I am totally clueless about doing this.
EDIT: Lot of edit.
public partial class Form1 : Form
{
// Static form. Null if no form created yet.
private static Form1 form = null;
private delegate void EnableDelegate(bool enable);
public Form1()
{
InitializeComponent();
form = this;
}
// Static method, call the non-static version if the form exist.
public static void EnableStaticTextBox(bool enable)
{
if (form != null)
form.EnableTextBox(enable);
}
private void EnableTextBox(bool enable)
{
// If this returns true, it means it was called from an external thread.
if (InvokeRequired)
{
// Create a delegate of this method and let the form run it.
this.Invoke(new EnableDelegate(EnableTextBox), new object[] { enable });
return; // Important
}
// Set textBox
textBox1.Enabled = enable;
}
}
This is just another method:
TextBox t = Application.OpenForms["Form1"].Controls["textBox1"] as TextBox;
You shouldn't really change UI controls in your Form from your class1, but instead create a method or a property in class1 that would tell if the textbox should be enabled or not.
Example:
// I changed the name class1 to MySettings
public class MySettings
{
public bool ShouldTextBoxBeEnabled()
{
// Do some logic here.
return true;
}
// More generic
public static bool SetTextBoxState(TextBox textBox)
{
// Do some logic here.
textBox.Enabled = true;
}
// Or static property (method if you like)
public static StaticShouldTextBoxBeEnabled { get { return true; } }
}
Then in your form:
MySettings settings = new MySettings();
textBox1.Enabled = settings.ShouldTextBoxBeEnabled();
// Or static way
textBox1.Enabled = MySettings.StaticShouldTextBoxBeEnabled;
// Or this way you can send in all textboxes you want to do the logic on.
MySettings.SetTextBoxState(textBox1);
You can pass the instance of your Form to the class
MyForm frm = new MyForm();
MyClass c = new MyClass(frm);
Then your class can take that instance and access the textbox
public class MyClass
{
public MyClass(MyForm f)
{
f.TextBox1.Enabled = false;
}
}
The design does not look OK
It is better to call the class in your form and based on the value returned, manipulate the textbox
//MyForm Class
MyClass c = new MyClass();
c.DoSomethings();
if(c.getResult() == requiredValue)
textBox1.enabled = true;
else
textBox1.enabled = false;
//MyForm Class ends here
UPDATE
public class Class1
{
public static int SomeFunction()
{
int result = 1;
return result;
}
public static void SomeFunction(out int result)
{
result = 1;
}
}
Usage
if(Class1.SomeFunction() == 1)
textBox1.Enabled = true;
else
textBox1.Enabled = false;
OR
int result = 0;
Class1.SomeFunction(out result);
if(result == 1)
textBox1.Enabled = true;
else
textBox1.Enabled = false;
You could let your class1 have an event to enable the Textbox.
public class Class1
{
public event Action<object, EventArgs> subscribe ;
private void raiseEvent()
{
var handler = subscribe ;
if(handler!=null)
{
handler(this,EventArgs.Empty);//Raise the enable event.
}
}
}
Let the class containing the TextBox subscribe to it somehow. In TextBox wrapper class
public class TextBoxWrapper
public void EnablePropertyNotification(object sender, EventArgs args)
{
TextBox1.Enabled = true ; //Enables textbox when event is raised.
}
public TextBoxWrapper()
{
class1Instance.subscribe+=EnablePropertyNotification ;
}
To access/modify a Form Element property, just write this in your outside Class.
Form1.ActiveForm.Controls["textBox1"].Enabled = true;
Where textBox1 is the variable name of TextBox.
What this actually does: Gets the active Form object's control specified by the name in string.
WARNING: Active form means the form which is currently open and focused on. If you do something else on your computer, with your minimized WindowsForm application, the Form1.ActiveForm will not get the form, instead, it will give null, which can lead to errors later. Be careful!
based on the answer from #vr_driver you can do that to avoid problems with other containers like groupbox, panels...
TextBox t = Application.OpenForms["Form1"].Controls.Find("textBox1", true)[0] as TextBox;
In this example you have a form called Main.cs and a class called MyClass:
In MyClass (Note: the name of my Form Class = 'Main'):
Main ui = new Main();
ui.toolStripProgressBarStickers.PerformStep();
In (FormName).Designer.cs so in my case Main.designer.cs change the appropriate control from 'private' to 'public':
public System.Windows.Forms.ToolStripProgressBar toolStripProgressBarStickers;
This solved it for me.
Thanks, Ensai Tankado
I had to do this at work and didn't find that any of these answers matched what I ended up doing, so I'm showing how I made it work.
First, initialize a copy of your class in your load event.
NameOfClass newNameofClass;
Then you want to bind to your class (in the load event):
textBox1.DataBindings.Add(new Binding("Enabled", newNameofClass, "textBox1Enabled"));
In your class, do the following:
private bool textBox1Enabled = false;
public bool TextBox1Enabled
{
get
{
return textBox1Enabled;
}
set
{
textBox1Enabled = value;
}
}
The false setting will initialize your textbox to being disabled
Set textBox1Enabled to true if you want to enable by default.
If you have other logic to enable/disable the textbox, simply modify the value of textBox1Enabled accordingly.
Very easy:
Create an Instance of your Form Object where want to access the Elements from.
Form1 ui = new Form1();
and now change the Form Elements to "public" - like this in the Designer Code:
...
public System.Windows.Forms.TextBox textBox6;
...
Now you can access them like this in your Code:
ui.textBox6 ...
I had the same problem. I used windows forms & Visual Studio to generate a UI in a utility with textbox, checkbox, and button controls but ALL the code was in the same class.
I'm rewriting the utility now that I know "more" OOP concepts and created actual objects and separate classes. I too had problems getting the separate classes to be able to access the form controls and any shared methods that are in the form class. I tried the various suggestions in this thread as well as other threads but none of those solutions worked for me.
What worked for me (not sure if its the right thing to do or not) was I had each class that needed to access the controls and forms methods inherit from the Form.
Here is the relevant part of the Form.cs file:
namespace Utility
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void WriteNote(string noteText, bool asHeading = false)
{
//Writes Messages to the Message box in the UI
Font font1 = new Font(this.ResultsTB.Font, FontStyle.Bold);
Font font2 = new Font(this.ResultsTB.Font, FontStyle.Regular);
if (asHeading)
this.ResultsTB.Font = font1;
else
this.ResultsTB.Font = font2;
this.ResultsTB.AppendText(noteText + "\r\n");
}
My Form contains a textbox called DirTB and a method called "WriteNote" that writes info to another textbox called ResultsTB. Here is the class (at least as far down as the first successful call of the WriteNote method from the Form:
namespace Utility
{
public class AppServerDTO : Form1
{
#region App Server attributes
//attributes listed here
#endregion App Server attributes
#region AppServerDTO Constructor
public AppServerDTO()
{
//These methods verify and set all the attributes
VerifyInstallFolder();
}//end of constructor AppServer
#endregion AppServerDTO Constructor
#region AppServerDTO class methods
public void VerifyInstallFolder()
{
string keypath = string.Empty;
string locationVerification = DirTB.Text + #"\SomeText";
for (int i = 0; i < 4; i++) //allows 3 attempts to get the install folder right
{
if (Directory.Exists(locationVerification))
{
i = 4;//Kills the loop
}
else if (!Directory.Exists(locationVerification))
{
locationVerification = DirTB.Text + #"\SomeMoreText";
}
else if (!Directory.Exists(locationVerification))
{
WriteNote("The directory listed in the Install Directoy box is not reachable.");
WriteNote("Please select the correct directory.");
WriteNote("The correct directory is the folder that contains the ApplicationUpdates & UpdateManager folders.");
WriteNote(#"i.e. C:\Somewhere or D:\Someplace\Somewhere");
var folderpath = FolderPrompt(#"C:\");
DirTB.Text = folderpath; //updates the install folder textbox to the new location
keypath = folderpath;
i++;
}
}//end for loop
}//end VerifyInstallFolder
As long as you are very careful with what you mark as public vs private, it should be ok.
This is how you should do :
I wrote the code below in my form class :
public static Form1 form = null;
private delegate void SetImageDelegate(Image image);
public Form1()
{
InitializeComponent();
form = this;
}
public static void SetStaticImage(Image image)
{
if (form != null)
form.pic1.Image = image;
}
private void setImage(Image img)
{
// If this returns true, it means it was called from an external thread.
if (InvokeRequired)
{
// Create a delegate of this method and let the form run it.
this.Invoke(new SetImageDelegate(setImage), new object[] { img });
return; // Important
}
// Set textBox
pic1.Image = img;
}
and the code below should be in anouther class :
Form1 frm= Form1.form;
frm.pic1.Image = image;
Note that i changed private static Form1 form = null; to public static Form1 form = null;
Good Luck ... Written by Hassan Eskandari :)
I have a parent form and a dialog. I need to pass info from the parent to the dialog
Here's what I have:
private void Item_Click(object sender, EventArgs e)
{
DialogResult result = DialogResult.OK;
DlgGraphOptions _frmDlgGraphOptions = new DlgGraphOptions();
_frmDlgGraphOptions.m_SerOpts = theDGroup.m_SerOpts;
_frmDlgGraphOptions.ShowDialog(this);
if (result == DialogResult.OK)
{
// Save the revised options to the Data Group
theDGroup.m_SerOpts = _frmDlgGraphOptions.m_SerOpts;
}
In DlgGraphOptions(child/dialog) form, I have intialitzed
public partial class DlgGraphOptions : Form
{
public GraphOpts_t m_SerOpts = new GraphOpts_t();
}
private void InitSettings(int idxSeries)
{
m_nMaxPts = m_SerOpts.GetMaxPts(idxSeries);
}
So I need to pass theDGroup.m_SerOpts from parent to the dialog,so I have done
_frmDlgGraphOptions.m_SerOpts = theDGroup.m_SerOpts;
in the parent. Now in the child:
public GraphOpts_t m_SerOpts = new GraphOpts_t;
This seems to be wrong. I don't want to be reinitializing it.
I think you should change your code in this way:
First, in the DlgGraphOptions form, change the constructor of DlgGraphOptions
// Force the caller to pass a GraphOpts_t
// Check if it is a valid instance or create one as new
public partial class DlgGraphOptions(GraphOpts_t input ) : Form
{
m_SerOpts = (input == null ? new GraphOpts_t() : input);
}
then create a public property with only the getter returning the internal GraphOpts
public GraphOpts_t Options
{
get{ return m_SerOpts; }
}
then, in the calling form, change uour code
// Pass the m_setOpts from theDGroup
DlgGraphOptions _frmDlgGraphOptions = new DlgGraphOptions(theDGroup.m_SerOpts);
if(DialogResult.OK == _frmDlgGraphOptions.ShowDialog(this))
{
// Save the revised (or new) options to theDGroup
theDGroup.m_SerOpts = _frmDlgGraphOptions.Options;
}
This approach will force the user of your dialog to pass an initialization value or null.
However your InitSettings will work with a initialized value and you don't have initialized two times your options instance.
(Actually there isn't a big improvement from your code, but I think it is a better approach)
Your child class should probably have the m_SerOpts as a property:
public partial class DlgGraphOptions : Form
{
public GraphOpts_t m_SerOpts { get; set; }
}
Your click event can probably be cleaned up like this:
private void Item_Click(object sender, EventArgs e)
{
using (DlgGraphOptions _frmDlgGraphOptions = new DlgGraphOptions()) {
_frmDlgGraphOptions.m_SerOpts = theDGroup.m_SerOpts;
if (_frmDlgGraphOptions.ShowDialog(this) == DialogResult.OK)
{
// Save the revised options to the Data Group
theDGroup.m_SerOpts = _frmDlgGraphOptions.m_SerOpts;
}
}
}
where in your DlgGraphOptions form, you need to set the form's DialogResult property in the OK or Save button event.
You could also just pass m_SerOpts object through the constructor:
public partial class DlgGraphOptions : Form
{
public GraphOpts_t m_SerOpts { get; }
public DlgGraphOptions(GraphOpts_t serOpts) {
InitializeComponents();
m_SerOpts = serOpts;
}
}
C#: Does Serializable() attribute prevent passing a class instance to another form?
I have the following classes, and is trying to build a settings module for my application. But when i try to access _configurator in settingForm method i get an exception: "object reference not set to an instance of an object". Why?
[Serializable()]
public class Config
{
public Config() { }
public string ComPort
{
get
{
return comPort;
}
set
{
comPort = value;
}
}
private string comPort;
}
public partial class kineticMoldDockUserControl : UserControl
{
private settingsForm setForm = null;
private Config _cf = null;
public kineticMoldDockUserControl()
{
InitializeComponent();
_cf = new Config();
_cf.ComPort = "COM12";
}
private void preferencesToolStripMenuItem_Click(object sender, EventArgs e)
{
if (!Application.OpenForms.OfType<settingsForm>().Any())
{
setForm = new settingsForm();
setForm.Show();
setForm.cf = _cf;
}
}
}
public partial class settingsForm : Form
{
Config _configutor = null;
public Config cf { get { return _configutor; } set { _configutor = value; } }
public settingsForm()
{
InitializeComponent();
try
{
MessageBox.Show(_configutor.ComPort.GetType().ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
You error has no relation with Serializable attribute. Problem lies in below lines of code:
setForm = new settingsForm();
setForm.Show();
setForm.cf = _cf;
SettingsForm constructor is using configurator but you are setting it after constructor is called. You may pass the configurator via constructor to solve your issue.
The code you pasted does not work because you access _configurator in the Constructor of settingsForm.
You should instead create a Constructor that accepts a Config instance.
The Serialization Attribute is not the cause of your error.
You're trying to display information about the configutor in the constructor, when the cf variable doesn't get set until after you show the form.
I'm going to go out on a limb and say that's it because you never instantiate your class. Only code I see is:
Config _configutor = null;;