Inheriting from a form c# - c#

everybody. My plan is to create a separate class, in which I would declare all the labels and textbox values. But to do so I have to inherit from a form. The problem is that when I inherit from a form my class becomes a form and calls elements from itself. Setting the properties of labels and textboxes to public did not help. Any ideas?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Assignment2v3
{
class Declarations : Form1
{
public List<Label> ErrRep
{ get; set; }
public List<TextBox> TextBoxes
{ get; set; }
public List<ComboBox> ComboBoxes
{ get; set; }
public Declarations()
{
ErrRep = DeclareErrorReports();
TextBoxes = DeclareTextBoxes();
ComboBoxes = DeclareComboBoxes();
}
List<Label> DeclareErrorReports()
{
var ER = new List<Label>();
ER.Add(errorReport1);
ER.Add(errorReport2);
ER.Add(errorReport3);
return ER;
}//Would be used if try catch worked
List<TextBox> DeclareTextBoxes()
{
List<TextBox> TextBoxes = new List<TextBox>();
TextBoxes.Add(textBoxPizza1);
TextBoxes.Add(textBoxPizza2);
TextBoxes.Add(textBoxPizza3);
return TextBoxes;
}//Puts all textBoxes into a list
List<ComboBox> DeclareComboBoxes()
{
var ComboBoxes = new List<ComboBox>();
ComboBoxes.Add(comboBoxPizza1);
ComboBoxes.Add(comboBoxPizza2);
ComboBoxes.Add(comboBoxPizza3);
return ComboBoxes;
}//Puts all comboboxes into a list
// ^ Boring declarations
}
}

You should probably inherit from UserControl instead. With your own UserControl, you can add it to one or more forms in one or more places.
There are plenty of tutorials out there which guide you in creating your own WinForms UserControl.

Related

Cannot declare a UserControl in file code

I have had a problem. I create an UserControl and I save it, it appears in ToolBox. I can drop it from ToolBox normally. However, I can not declare it as a variable in the file code. Can you help me, please? And it is file code of UserControl
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Music_Player_Project_IT008N13.Controls;
namespace Music_Player_Project_IT008N13.Music_design_User_Control
{
public partial class LocationPanel : UserControl
{
public LocationPanel()
{
InitializeComponent();
}
public delegate void DoEvent(string maSo, string tenSV, string khoa, string diemTB);
public event DoEvent RefeshDgv;
private void btnDelete_Click(object sender, EventArgs e)
{
}
}
}
When you "drop it from the ToolBox normally", the Designer generates a member declaration for a new user control and also adds it to the forms Control collection. As I understand it, your question states that you would like to declare your user control variable in code. If this is the goal, we have to do the same thing that the Designer would do and add it to the Controls collection of the container you want to put it in.
Example
Add a FlowLayoutPanel using code, then add 3 CustomUserControls to it also in code.
public partial class MainForm : Form
{
public MainForm() => InitializeComponent();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// Declare a flow layout panel in code.
// Add it to the main form control collection
var flowLayoutPanel = new FlowLayoutPanel
{
Name = "flowLayoutPanel",
Dock = DockStyle.Fill,
};
this.Controls.Add(flowLayoutPanel);
for (char c = 'A'; c < 'D'; c++)
{
var userControl = new CustomUserControl
{
Name = $"userControl{c}", // No space, start with lowercase
Text = $"UserControl {c}", // Visible name
Margin = new Padding(10, 2, 10, 2),
Width = flowLayoutPanel.Width - 20,
};
flowLayoutPanel.Controls.Add(userControl);
}
// T E S T
CustomUserControl? loopback = GetUserControl("userControlA");
Debug.Assert(loopback != null, "Expecting to retrieve user control by name");
}
Then, to use the control, retrieve it from the Controls collection by name.
CustomUserControl? GetUserControl(string name)
{
var layoutPanel = Controls["flowLayoutPanel"] as FlowLayoutPanel;
return layoutPanel.Controls[name] as CustomUserControl;
}
}
Where:
public partial class CustomUserControl : UserControl
{
public CustomUserControl() => InitializeComponent();
public new string Text
{
get => label1.Text;
set => label1.Text = value;
}
}

Textbox readonly property not working in TextBox made by me

I have a textbox (TextBoxMoeda) made by me, but, even when the textbox property readonly is set true. nothing happens. Anyone knows how to implement the code to resolve this problem?. Please help me?
public class TextBoxMoeda : TextBox
{
private double dp;
private string fmt = string.Empty;
private int _CasasDecimais = 0;
[Category("TextBoxMoeda")]
public virtual bool SomenteLeitura
{
get => base.ReadOnly;
set
{
base.ReadOnly = value;
Invalidate();
}
}
//Code Continues .......
}
WPF
You want the IsReadOnly property, not the ReadOnly property.
For example:
Create a new WPF App (.NET Framework) project called DeleteMe
In MainWindow.xaml, delete the Grid
In MainWindow.xaml.cs, use this code:
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace DeleteMe
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var tm = new TextBoxMoeda();
this.AddChild(tm);
tm.SomenteLeitura = true;
}
public class TextBoxMoeda : TextBox
{
[Category("TextBoxMoeda")]
public virtual bool SomenteLeitura
{
get => base.IsReadOnly;
set
{
base.IsReadOnly = value;
}
}
}
}
}
The textbox will be readonly (i.e. I can't type anything into the textbox).
WinForms
The code already appears to work in WinForms. These steps will produce a working project:
Create a new Windows Forms App project called DeleteMeAgain
Overwrite all of the Form1.cs code with this:
using System.ComponentModel;
using System.Windows.Forms;
namespace DeleteMeAgain
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var tm = new TextBoxMoeda();
this.Controls.Add(tm);
tm.SomenteLeitura = true;
}
public class TextBoxMoeda : TextBox
{
[Category("TextBoxMoeda")]
public virtual bool SomenteLeitura
{
get => base.ReadOnly;
set
{
base.ReadOnly = value;
Invalidate();
}
}
}
}
}
The textbox will be readonly (i.e. I can't type anything into the textbox).
Windows Form: User Control
Do this:
Create a new Windows Forms App called DeleteMe3
Set Target Framework to .NET Core 3.1 (Long-term support)
In your project, create a new UserControl with the filename TextBoxStack.cs
Overwrite all of the code for that user control with this:
using System.ComponentModel;
using System.Windows.Forms;
namespace DeleteMe3
{
public partial class TextBoxStack : TextBox
{
[Category("TextBoxStack")]
public virtual bool SomenteLeitura
{
get => base.ReadOnly;
set
{
base.ReadOnly = value;
Invalidate();
}
}
}
}
An error will appear. Go to the source of the error and delete that line.
Build the solution
Add your new user control to Form1
Select the new user control on the form
Change the SomenteLeitura property to True
Run the project. The textbox should be grey and readonly.

How to create TextBoxes in a GroupBox using the Collection Editor window?

I would like to create a customized control that inherits from GroupBox and have a property that is a collection of TextBox. I intent to create in Designer as many TextBoxes as I want, similarly what could be done with TabControl, which one could create pages in TabPages properties through the Collection Editor window.
I created the property TextBoxList that appears in properties window and when I click in the “…” Collection Editor window opens to create the TextBox and set its properties, but when I click the ok button, none TextBox is added to my GroupBox. The TextBox instances were created, but were not added to the GroupBox. Does somebody could help me with the TextBox addition to the GroupBox? Follows the code.
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Forms;
namespace CustomizedControl
{
public partial class GroupBoxWithTextBox : GroupBox
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Editor(typeof(System.ComponentModel.Design.CollectionEditor),
typeof(System.Drawing.Design.UITypeEditor))]
[Description("The TextBoxes in GroupBox control."), Category("Behavior")]
public Collection<TextBox> TextBoxList
{
get
{
return _textBoxList;
}
}
private Collection<TextBox> _textBoxList = new Collection<TextBox>();
public GroupBoxWithTextBox()
{
InitializeComponent();
}
}
}
Based on my research, we need to override the class CollectionEditor if we want to add the textbox in design.
I write the following code and you can have a look.
Code:
[Serializable]
public partial class GroupBoxWithTextBox : GroupBox
{
public GroupBoxWithTextBox()
{
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
Padding = new Padding(0);
textBox = new TextBox();
textBox.Size = new System.Drawing.Size(60, 30);
Controls1.Add(textBox);
textBox.Dock = DockStyle.Top;
}
[EditorAttribute(typeof(NewCollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
public ControlCollection Controls1
{
get
{
return base.Controls;
}
set
{
}
}
private TextBox textBox;
}
public partial class NewCollectionEditor : CollectionEditor
{
public NewCollectionEditor(Type t) : base(t)
{
}
// *** Magic happens here: ***
// override the base class to SPECIFY the Type allowed
// rather than letting it derive the Types from the collection type
// which would allow any control to be added
protected override Type[] CreateNewItemTypes()
{
Type[] ValidTypes = new[] { typeof(TextBox) };
return ValidTypes;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
return base.EditValue(context, provider, value);
}
}
Result:(You need to set the textbox location manually)
Hope this could help you.

Design UserControl with Textbox and Label with Properties in grid

Check the image of form and see the below code to get that functionality
Here is some code which i had done.
I am working on user control library project and i drag a label and textbox on it.
Please check the code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CustomControls
{
public partial class CustomTextbox: UserControl
{
public enum Directions
{
Left, Right, Top, Bottom
}
[Description("Define the Text Property of label")]
public string Description {
get
{
return label1.Text;
}
set
{
label1.Text = value;
}
}
[Description("Define the location of label")]
public Point LabelLocation
{
get
{
return label1.Location;
}
set
{
label1.Location = value;
}
}
[Description("Define the location of Textbox")]
public Point TextboxLocation
{
get
{
return textBox1.Location;
}
set
{
textBox1.Location = value;
}
}
[Description("Set Password Character Input in Textbox")]
public char PasswordChar
{
get
{
return textBox1.PasswordChar;
}
set
{
textBox1.PasswordChar = value;
}
}
[Description("Set the Multiline feature of Textbox")]
public bool MultiLine
{
get
{
return textBox1.Multiline;
}
set
{
textBox1.Multiline = value;
}
}
public CustomTextbox()
{
InitializeComponent();
}
}
}
I had declare an enum name direction so that i can change the position of label control as per value selected in Property Grid (left, right, down, up) and as per selected value label should align in project where i used the control dll.
Similarly i also want to create events for textbox like text validating and other important events of the controls.
How can i do this. Please suggest?
As par my understanding you need your own custom event from user control.
First define delegates and events in your user control as follow.
public delegate void TextChangeDelegate(object obj, string str);
public event TextChangeDelegate TextChanged;
Now in your user control you need to rise this event from your custom condition.
if(this.TextChanged != null)
{
this.TextChanged.Invoke(this, textBox1.Text);
}
Use this in you form where you use this as follow.
userControl.TextChanged += UserControl_TextChanged;

Controls not working

I have added my main class, from which I call buttons class, and that's where it's supposed to print out the button. The code is compiling ok, but I can't see the actual button. Seems to me it didnt inherit the controls properties. Thank you!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows;
//main class
namespace Test
{
public partial class Form1 : Form
{
buttons button1;
public Form1()
{
InitializeComponent();
print_button();
}
private void print_button()
{
button1 = new buttons();
button1.print();
}
}//form
}//test
//---------------------------------------------------------------//
//buttons class
namespace Test
{
public class buttons : System.Windows.Forms.Control
class buttons
{
private Button button1;
public buttons()
{
}
public void print()
{
button1 = new Button();
button1.Location = new System.Drawing.Point(82, 44);
button1.Size = new System.Drawing.Size(977, 54);
button1.Text = "next";
Controls.Add(button1);
}
}//class
}//test
I have no idea what you are trying to accomplish with the code you have provided. In any event the reason this method doesn't work:
public void print()
{
button1 = new Button();
button1.Location = new System.Drawing.Point(82, 44);
button1.Size = new System.Drawing.Size(977, 54);
button1.Text = "next";
Controls.Add(button1);
}
is because the class 'buttons' does not define a Controls collection nor does it inherit from a class that exposes a controls collection. For example if you were to do this:
public class buttons : System.Windows.Form
{
...
}
Your code would then at least compile since the Form class exposes a Controls collection. It isn't entirely apparent what you are trying to accomplish though so this solution may not suit your needs. Post more information as appropriate and I will do what I can to help you.
-----Edit
It seems like you are trying to refactor your Form1 class from one of your comments above.
You could do something like this:
public class Form1 : Form
{
public void foo()
{
Controls.Add(buttons.print());
}
}
and modify your buttons class as:
public class buttons
{
public static Button print()
{
Button btn = new Button();
btn.Location = new System.Drawing.Point(82, 44);
btn.Size = new System.Drawing.Size(977, 54);
btn.Text = "next";
return btn;
}
}
This will then add a button to your main form's control collection once it is called. As wrote though this method is useless since it can only produce the same button over and over. I would modify the method so that it looks like this
public static Button print(Point buttonLocation, Size buttonSize, string buttonText)
{
Button btn = new Button();
btn.Location = buttonLocation;
btn.Size = buttonSize;
btn.Text = buttonText;
return btn;
}
And then the main form looks like this:
public void foo()
{
Controls.Add(buttons.print(new System.Drawing.Point(82, 44), new System.Drawing.Size(977, 54), "button text"));
}
Does this help?
--- Edit 2 ---
I am supplying this edit as a strictly academic example of how you could keep your main class (Form) 'cleaner' per the OP's request in the comments. I don't suggest using this method in production and would instead recommend using a pattern such as MVC, MVP, or MVVP. I am excluding examples of those patterns here because I think they exceed the skill level of the OP at this point in time and would only lead to more confusion.
Consider the following:
public class buttons
{
private Form _form = null;
public buttons(Form form)
{
_form = form;
}
public void print(Point buttonLocation, Size buttonSize, string buttonText)
{
Button btn = new Button();
btn.Location = buttonLocation;
btn.Size = buttonSize;
btn.Text = buttonText;
_form.Controls.Add(btn);
}
}
public class Form1 : Form
{
private buttons _buttons = null;
public Form1()
{
_buttons = new buttons(this);
}
public void foo()
{
buttons.print(new System.Drawing.Point(82, 44), new System.Drawing.Size(977, 54), "button text");
}
}
Now here is what is happening: when Form1 is instantiated it creates a new instance of the buttons class and passes a reference of itself into the buttons constructor (_buttons = new buttons(this)) internally the buttons class sets this reference to the local variable _form so, therefore, anything you do to the variable _form well be like if you were doing it directly to Form1. As you can see that is what happens in the print() method where a button is created and then added to the Controls collection of _form which is the same as calling Controls.Add from within Form1.
Does this make sense to you?
Your class buttons isn't a subclass of System.Windows.Forms.Control so it has no this.Controls member.
I suggest use use the WinForms Designer in VS instead of creating your own forms or controls by hand, at least while you're a beginner.
I also note that you should conform to .NET style conventions. Classes and public members should use TitleCase and should exist within a namespace. Change buttons to Buttons (if you want to use that name) and wrap it in a namespace block.

Categories