In which form event I can hide label of user control - c#

In a windows application project I have a form which used a user control. I want to hide a label and textbox on user control. In which event of form I can do this ?
This method in user control which named DoctorPermissionApprove:
public void LoadDoctorPermission(int fromWhere)
{
if (fromWhere == 0) // Başhekimden geldiyse?
{
labelDoctor.Visible = true;
editDoctorWithoutHead.Visible = true;
}
else if (fromWhere == 1) // Normal Hekimden geldiyse
{
labelDoctor.Visible = false;
editDoctorWithoutHead.Visible = false;
}
}
And in form:
private void ExistRequestAndNewEntryForm_Shown(object sender, EventArgs e)
{
var obj = new DoctorPermissionApprove();
obj.LoadDoctorPermission(0);
}
For example I tried in shown event. But it still visible
I want to hide or show this components when the anybody open the form
Thank you a lot

In the UserControl class add a public property to set the internal label visibility true or false. This can be accessed from your parent form where your usercontrol is added.
Example:
public class YourUserControl
{
//This code will be in designer class
private Label lblYourLabelToHide = new Label();
//Create this public property to hide the label
public bool IsLabelVisible
{
set { lblYourLabelToHide.Visible = value; }
}
}
public class YourParentForm
{
//This will be in designer
private YourUserControl userControl = new YourUserControl();
public void Form_Load()
{
//based on some criteria
userControl.IsLabelVisible = false;
}
}

Related

Changing form control from user control

I'm trying to changing a user control informations (labels, pictures etc.) from auto added user control. But i cant do it.
Here's my code;
private void KitapButton_Click(object sender, EventArgs e)
{
BıtıkForm BForm = new BıtıkForm();
BForm.kitapGoruntuleme.Visible = true;
}
public partial class BıtıkForm : Form
{
//create controls public instance
public Label label;
public BıtıkForm()
{
InitializeComponent();
//initialize the control
label = new Label();
}
}
Now you can access it from other place like;
BıtıkForm BForm = new BıtıkForm();
BForm.label.Visible = true;
/////// But my Suggestion do not do it like that instead do it like below ///////
BıtıkForm BForm = new BıtıkForm(controlVisible);//Pass the bool value as parameter to the constructor of form
BForm.Show();
And then in form
public partial class BıtıkForm : Form
{
public BıtıkForm(bool controlVisible)
{
InitializeComponent();
//Set Control Visibility
someControl.Visible = controlVisible;
}
}
I didn't use C# too much but It's eventually object oriented. The mistake I made is; I was creating a new instance of 'BıtıkForm' everytime event fired. It could be solved by adding new property where event belongs, and property will carry 'BıtıkForm' object. So It can be managed trough all over the program.

Setting default size/text of custom control in c#

I am creating a custom control in my C# application in order to add a new property (MyProperty below). It is inheriting from Label. One thing I would like it to do, is display at a particular size when I drag it on to my form (200x132). I'd also like it to display no text. However, no matter how I try to do this, it doesn't seem to work. I am able to set BackColor and BorderStyle with no problem, however. I'm fairly new to C#, so maybe I'm missing something obvious.
Here is my code:
using System.Drawing;
using System.Windows.Forms;
namespace MyProgram
{
public enum MyEnum
{
Value1, Value2, Value3
}
public partial class MyControl : Label
{
public MyControl()
{
BackColor = Color.LightCoral;
BorderStyle = BorderStyle.FixedSingle;
AutoSize = false;
Size = new Size(200, 132);
Text = "";
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
private MyEnum myProperty;
public MyEnum MyProperty
{
get { return myProperty; }
set { myPropery = value; }
}
}
}
The answer provided via Dispersia's link has a bug, in my opinion. The text reset should happen once and then whatever a user does after that shouldn't matter. In Dispersia's link you can't actually set the text back to the control name because it will keep blanking it out.
The answer provided by cramopy doesn't technically answer your question, it is a way to do it by using the defaults on a UserControl though. You'll also need to bind the Text property of the UserControl to the label's.
The following should work while inheriting from a Label and will only reset the Text property once.
public partial class MyControl : Label
{
#region fields
private IComponentChangeService _changeService;
private bool canResetText = false;
#endregion
#region properties
protected override Size DefaultSize
{
get { return new Size(200, 132); }
}
[Browsable(false)]
public override bool AutoSize
{
get { return false; }
set { base.AutoSize = false; }
}
public override ISite Site
{
get { return base.Site; }
set
{
base.Site = value;
if (!base.DesignMode)
return;
this._changeService = (IComponentChangeService)base.GetService(typeof(IComponentChangeService));
if (this._changeService != null)
this._changeService.ComponentChanged += new ComponentChangedEventHandler(this.OnComponentChanged);
}
}
#endregion
#region constructors
public MyControl()
{
base.BackColor = Color.LightCoral;
base.BorderStyle = BorderStyle.FixedSingle;
}
#endregion
#region methods
protected override void InitLayout()
{
base.InitLayout();
this.canResetText = true;
}
private void OnComponentChanged(object sender, ComponentChangedEventArgs ce)
{
if (ce.Component != null &&
ce.Component == this &&
ce.Member.Name == "Text" &&
base.DesignMode &&
this.canResetText)
{
((MyControl)ce.Component).Text = string.Empty;
this.canResetText = false;
if (this._changeService != null)
this._changeService.ComponentChanged -= new ComponentChangedEventHandler(this.OnComponentChanged);
}
}
#endregion
}
#Dispersia reply only answers the myControl1 thing. (deleted meanwhile)
Here comes a full guide for solving your problem:
Add a new UserControl named MyLabel
Change the following within Designer Mode:
BorderStyle:= FixedSingle
Size:= 200; 132
Now Drag&Drop a new Label onto the control
Edit those Label values (also within Designer Mode):
AutoSize:= false
BackColor:= LightCoral
Dock:= Fill
Text:= clear/empty this box!! (don't write this inside the box, you really have to clear it!)
TextAlign:= MiddleCenter
Just recompile your project && add a MyLabel control from the Toolbar.
Now it show up as you wanted!!

Checking each event in winforms

I'm changing the visibility of some labels on the form , when a contol is moved. When all labels are invisible , i want to close application. Is there a way to do this ?
You can keep track of how many visible Label controls there are, and when the count reaches 0, you can close your form (or perform whatever other action is required to close the program in your case).
For example:
partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
int visibleLabelCount = 0;
foreach (Label label in Controls.OfType<Label>())
{
// Check property, in case some Label is initialized as not
// visible in the Designer
if (label.Visible)
{
visibleLabelCount++;
}
label.VisibleChanged += (sender, e) =>
{
visibleLabelCount += ((Label)sender).Visible ? 1 : -1;
if (visibleLabelCount <= 0)
{
Close();
}
}
}
}
}
The above attaches an event handler to each Label control found in your Form class, and at the same time counts the currently-visible Label controls. The event handler adjusts the count of visible Label controls as the visibility of each changes; if a Label becomes visible, the count is increased, if it becomes not visible, it's decreased. If the count reaches zero, the Form's Close() method is called to close the form and the program.
Create a function like this:
public void CheckLabels()
{
bool AllHidden = true;
foreach (Control c in this.Controls)
{
if (c.GetType().Name == "Label")
{
if (c.Visible == true)
{
AllHidden = false;
Break;
}
}
}
if (AllHidden)
{
//Do whatever you want. For example:
this.Close();
}
}
Call this function from a button click event of Visibility_Changed event of all labels.
EDIT:
Another way is create your own label by inheriting from System.Windows.Forms.Label.
public partial class MyLabel : System.Windows.Forms.Label
{
public MyLabel()
{
InitializeComponent();
this.VisibleChanged += new EventHandler(MyLabel_VisibleChanged);
}
void MyLabel_VisibleChanged(object sender, EventArgs e)
{
CheckLabels();
}
public void CheckLabels()
{
bool AllHidden = true;
foreach (System.Windows.Forms.Control c in this.FindForm().Controls)
{
if (c.GetType().Name == "MyLabel")
{
if (c.Visible == true)
{
AllHidden = false;
break;
}
}
}
if (AllHidden)
{
//Do whatever you want. For example:
this.FindForm().Close();
}
}
And use MyLabel in your form. Thats it!!

Accessing Form's Controls from another class

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 :)

C# Property Grid

I am writing an application which is going to allows users to change the properties of a text box or label and these controls are user controls. Would it be easiest to create a separate class for each user control which implements the properties I want them to be able to change and then bind those back to the user control? Or is there another method I am overlooking?
Create a custom Attribute, and tag the properties you want the user to edit with this attribute. Then set the BrowsableAttribute property on the property grid to a collection containing only your custom attribute:
public class MyForm : Form
{
private PropertyGrid _grid = new PropertyGrid();
public MyForm()
{
this._grid.BrowsableAttributes = new AttributeCollection(new UserEditableAttribute());
this._grid.SelectedObject = new MyControl();
}
}
public class UserEditableAttribute : Attribute
{
}
public class MyControl : UserControl
{
private Label _label = new Label();
private TextBox _textBox = new TextBox();
[UserEditable]
public string Label
{
get
{
return this._label.Text;
}
set
{
this._label.Text = value;
}
}
[UserEditable]
public string Value
{
get
{
return this._textBox.Text;
}
set
{
this._textBox.Text = value;
}
}
}

Categories