C# - Add custom property/attribute to new button - c#

I try to developp an app for users to create a lot of computer's configuration, with OS / Language / etc ...
When he validate a configuration, I would like the choices to be stored in a custom attribute button
private void VALIDATE_Click(object sender, EventArgs e)
{
string Computer = Text_Computer.Text;
if (myList.Any(str => str.Contains(Computer)))
{
MessageBox.Show(Computer+"Already Exist");
}
else
{
Button button = new Button();
button.Size = new System.Drawing.Size(195, 30);
button.Tag = Computer;
button.Name = Computer;
button.Text = Computer;
button.CustomOS = comboBox_OS.SelectedItem;
button.CustomLanguage = comboBox_Language.SelectedItem;
flowLayoutPanel3.Controls.Add(button);
myList.Add(Computer);
MessageBox.Show(Computer + "added");
}
In my GUI, if Users want to edit a configuration, he click on the new button representing the configuration and all choices are back, like :
comboBox_OS.SelectedItem = button.CustomOS;
comboBox_Language.SelectedItem = button.CustomLanguage;
Is that possible to create my custom attribute like button.CustomOS and button.CustomLanguage ?
Regards

It is possible and quite easy. You just derive a new class from the original Button and declare two new Properties. I included the code into a simple example.
using System;
using System.Windows.Forms;
namespace StackOverflow
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
}
private void cbOS_SelectedIndexChanged(object sender, EventArgs e)
{
//Save selection.
ComboBox cb = (ComboBox)(sender);
btn1.CustomOS = cb.SelectedItem.ToString();
}
private void btnSelect_Click(object sender, EventArgs e)
{
//Restore selection on click.
MyButton btn = (MyButton)(sender);
cbOS.SelectedItem = btn.CustomOS;
}
//Declare a new class deriving from the original Button.
public class MyButton : Button
{
public String CustomOS { get; set; }
public String CustomLanguage { get; set; }
}
}
}

Related

How to change tab name and favicon in EasyTabs?

I am currently using EasyTabs for C#, and it's working fine but I need to be able to at least change the title of the tab from my application, and I can't seem to find anything that will let me do that so far. I'm talking about changing the tab name not the entire form name just the tab names at the top of the screen.
so I need to be able to take a variable from Form1 and change the tab name, again not all the tabs, but specific tabs that get opened, depending on the page, the variable will be different and each tab needs to be named respectively, just as it would if you were going to different sites in different tabs in chrome.
I have looked at all possible stack overflow questions that already exist and none have really helped, so any help on this would be greatly appreciated, and at this point, I would be happy with even only have tab names and not being able to change the favicon, but both would be amazing.
AppContainer.cs
using System;
using EasyTabs;
public partial class AppContainer : TitleBarTabs
{
public AppContainer()
{
InitializeComponent();
AeroPeekEnabled = true;
TabRenderer = new ChromeTabRenderer(this);
Icon = Properties.Resources.icon;
Text = "Example";
}
public override TitleBarTab CreateTab()
{
return new TitleBarTab(this)
{
Content = new Form1
{
Text = "New Tab"
}
};
}
private void AppContainer_Load(object sender, EventArgs e)
{
}
}
Form1.cs
using EasyTabs;
using System.Windows.Forms;
public partial class Form1 : Form
{
protected TitleBarTabs ParentTabs
{
get
{
return (ParentForm as TitleBarTabs);
}
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
Program.cs
using System.Windows.Forms;
using EasyTabs;
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
AppContainer container = new AppContainer();
container.Tabs.Add(
new TitleBarTab(container)
{
Content = new Form1
{
Text = "New Tab"
}
}
);
container.SelectedTabIndex = 0;
TitleBarTabsApplicationContext applicationContext = new TitleBarTabsApplicationContext();
applicationContext.Start(container);
Application.Run(applicationContext);
}
}
I've seen the answer before on github a while back, you can change the tab name using ParentTabs.SelectedTab.Caption = e.Title;
I'm not entirely sure where "ParentTabs" was supposed to be located though, if you figure it out please update us
Edit; Sorry for the vague answer. In order to have the ParentTabs variable, you need this code:
protected TitleBarTabs ParentTabs
{
get
{
return (ParentForm as TitleBarTabs);
}
}
You will also need to invoke a new action and Redraw the tabs, using ParentTabs.RedrawTabs();
if you wish to show a favecon and have a title show then use the following
Favecon Code:
private void WebUI_AddressChanged(object sender, AddressChangedEventArgs e)
{
_ = this.Invoke(new MethodInvoker(() =>
{
URLSearch.Text = e.Address;
{
Uri url = new Uri("https://" + new Uri(WebUI.Address).Host + "/favicon.ico");
try
{
Icon img = new Icon(new System.IO.MemoryStream(new
WebClient().DownloadData(url)));
this.Icon = img;
}
catch (Exception)
{
this.Icon = Properties.Resources.tempIcon;
//change tempIcon to your desired icon, extension is .ico
}
}
}));
}
and this is for your Title Code:
private void WebUI_TitleChanged(object sender, TitleChangedEventArgs e)
{
this.Invoke((Action)delegate
{
FindForm().Text = e.Title;
});
}
and for all of this to work then you need to use the AddressChanged and TitleChanged Event in your main form like so
WebUI.AddressChanged += WebUI_AddressChanged;
WebUI.TitleChanged += WebUI_TitleChanged;
and that should wrap things up, i hope this helped you.

Label will not show even when told to show

I am making an application that loads a separate form, the user puts in information, and then when done, it will show up on the primary form the application loaded with first.
The issue is that I tried multiple solutions to get this to load in, but it will not load in after the information is put in. I have tried this.Controls.Add(Label); which is what I have seen the most, but it has not worked. Another way I tried was doing Label.Show();, but the same result, with nothing showing. The AddContacts(string Name) method below is how I add the contact
The AddContact_Click(object sender, EventArgs e) method is a button that, when pressed, opens another form that allows information to be inserted.
public partial class Phonebook : Form
{
public Phonebook()
{
InitializeComponent();
MaximumSize = new Size(633, 306);
}
private void AddContact_Click(object sender, EventArgs e)
{
MakeContact MC = new MakeContact();
MC.Show();
}
public void AddContacts(string Name)
{
Label name = new Label();
//Added Style and Location of Label...
name.Text = Name;
name.Location = new Point(98, 13);
name.Font = new Font("Microsoft Sans Serif", 13, FontStyle.Bold);
this.Controls.Add(name);
Refresh();
}
}
Below is the Method I used when the Finish button is pressed, for when the user is done with the information, and then the AddContacts() method is called
public partial class MakeContact : Form
{
public MakeContact()
{
InitializeComponent();
MaximumSize = new Size(394, 377);
}
private void FinishContact_Click(object sender, EventArgs e)
{
//FullName is the name of the TextField when asking for a name
string Name = FullName.Text;
Phonebook PB = new Phonebook();
PB.AddContacts(Name);
//Closes Separate Form and goes back to the
Close();
}
}
Expectation:
It should load the label into the form after the information is put in.
Actual:
It will not show what so ever.
EDIT: Added More to the Code and to the Question since I didn't do too good of asking the question, sorry about that :/
An example of what I described in the comments:
When you do this:
Phonebook PB = new Phonebook();
you create a new instance of the PhoneBook class (your form): this is not the same Form instance (the same object) that created the MakeContact Form and the one you're trying to update. It's a different object.
Whatever change you make to this new object, it will not be reflected in the original, existing, one.
How to solve:
Add a Constructor to the MakeContact Form that a accepts an argument of type PhoneBook and a private object of type Phonebook:
private PhoneBook pBook = null;
public MakeContact() : this(null) { }
public MakeContact(PhoneBook phoneBook)
{
InitializeComponent();
this.pBook = phoneBook;
}
Assign the argument passed in the constructor to the private field of the same type. This Field will then used to call Public methods of the PhoneBook class (a Form is a class, similar in behaviour to other class).
It's not the only possible method. You can see other examples here.
Full sample code:
public partial class Phonebook : Form
{
private void AddContact_Click(object sender, EventArgs e)
{
MakeContact MC = new MakeContact(this);
MC.Show();
}
public void AddContacts(string Name)
{
Label name = new Label();
// (...)
this.Controls.Add(name);
}
}
public partial class MakeContact : Form
{
private PhoneBook pBook = null;
public MakeContact() : this(null) { }
public MakeContact(PhoneBook phoneBook)
{
InitializeComponent();
this.pBook = phoneBook;
}
private void FinishContact_Click(object sender, EventArgs e)
{
string Name = FullName.Text;
this.pBook?.AddContacts(Name);
this.Close();
}
}

How to pass data between WPF forms

I need help passing data from one WPF form to another. I have a main window with two other windows that will prompt the user for information. I want to end up with all the information in the first form so that I can store the data later on. The second form must return the Reservation and Room information when you click the OK button on the second form. The third form must return the Person information when you click OK.
public partial class MainWindow : Window
{
private string message;
public MainWindow()
{
InitializeComponent();
}
protected void Exit_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
protected void Create_Reservation_Click(object sender, RoutedEventArgs e)
{
Reservation PersonReservation = new Reservation();//Create a reservation instance
Room PersonRoom = new Room(); //Create an instance of a room
Person myPerson = new Person();//Create an instance of a person
CreateResRoom createReservationRoom = new CreateResRoom();//Create a instance of the CreateReservation WPF Form
createReservationRoom.Show();
Here it is supposed to set the room, reservation and person instance that I created equil to their corresponding instances in the CreateResRoom class.
I think the problem lies here, because it keeps continuing before it opens the CreateResRoom form.
PersonRoom = createReservationRoom.myRoom;
PersonReservation = createReservationRoom.myReservation;
}
}
That was my first class, the second and third will follow.
public partial class CreateResRoom : Window
{
Person myPerson;
public CreateResRoom()
{
InitializeComponent();
myReservation = new Reservation();
myRoom = new Room();
myPerson = new Person();
}
public Room myRoom
{
get;
set;
}
public Reservation myReservation
{
get;
set;
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void btnOk_Click(object sender, RoutedEventArgs e)
{
myRoom.RoomBeds = txtHeadCount.Text;
myRoom.RoomNumber = 1;
myRoom.RoomPrice = 20;
myRoom.RoomType = cboRoomType.Text;
myReservation.ResEndDate = dpEnd.ToString();
myReservation.ResStartDate = dpStart.ToString();
CreateRes createReservation = new CreateRes();
createReservation.Show();
//I think the same problem lies here that is in the MainWindow.
myPerson = createReservation.myPerson;
this.Close();
}
}
And the last class follows:
public partial class CreateRes : Window
{
public Person myPerson
{
get;
set;
}
public CreateRes()
{
InitializeComponent();
myPerson = new Person();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
private void btnOk_Click(object sender, RoutedEventArgs e)
{
myPerson.FirstName = txtFName.Text;
myPerson.LastName = txtLName.Text;
myPerson.IdNumber = Convert.ToInt32(txtIdNumber.Text);
myPerson.PhoneNumber = Convert.ToInt32(txtPhoneNumber.Text);
myPerson.AddressCity = txtAddressCity.Text;
myPerson.AddressStreet = txtAddressStreet.Text;
myPerson.AddressProvince = txtAddressProvince.Text;
myPerson.AddressPostalCode = txtAddressPostalCode.Text;
this.Close();
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
Just make a overload constructor which takes parameters of the window in which you want to retrieve.
Example:
Suppose we want a user to login from our MainWindow( i.e Login Window ) and we want to pass an int ID / string Email to our second form to retrieve data of logging user.
Than We have to first overload our second wpf form constructor. You can either make default constructor to do this or make an overload constructor for this work.
SecondForm:
public secondForm()
{
//Your Default Constructor Logic
}
public secondForm(string email_ )
{
//Your Overload Constructor Logic
}
Now in MainWindow from where we are logging and passing our EMail
MainWindow:
public void btnLogin()
{
//On Success
SecondWindow sw = new SecondWindow(txtBoxEMail.Content);
sw.Show();
}
A pattern you can use for this sort of thing is to have each form be responsible for creating the instance on ok click and then provide the object via a property get.
public partial class SomeForm: Window
{
public SomeClass MyProperty { get; private set; }
private void btnOk_Click(object sender, RoutedEventArgs e)
{
this.MyProperty = new SomeClass();
//additional setter logic here
this.Close();
}
}
Then you would access it from a parent form like this (notice the use of ShowDialog() http://msdn.microsoft.com/en-us/library/system.windows.window.showdialog(v=vs.110).aspx for easy checking of whether ok was clicked or not).
protected void Create_Reservation_Click(object sender, RoutedEventArgs e)
{
SomeClass myObj;
SomeOtherClass myOtherObj;
SomeForm myForm = new SomeForm();
if(myForm.Show().Value)
{
myObj = myForm.MyProperty;
}
SomeOtherForm myOtherForm = new SomeOtherForm();
if(myOtherForm.ShowDialog().Value)
{
myOtherObj = myOtherForm.MyOtherProp;
}
//save myObj & myOtherObj or whatever you need to do with them
Use the "normal way", here is a short overview.
First create a Data Context:
public class DC_Reservation() : INotifyPropertyChanged {
protected Reservation _PersonReservation ;
public Reservation PersonReservation {
get { return _PersonReservation ; }
set {
_PersonReservation = value;
NotifyPropertyChanged("PersonReservation ");
}
}
protected Room _PersonRoom ;
public Room PersonRoom {
get { return _PersonRoom ; }
set {
_PersonRoom = value;
NotifyPropertyChanged("PersonRoom");
}
}
protected Person _myPerson ;
public Person myPerson {
get { return _myPerson ; }
set {
_myPerson = value;
NotifyPropertyChanged("myPerson ");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged( string PropertyName ) {
if ( PropertyChanged != null ) {
PropertyChanged( this, new PropertyChangedEventArgs( PropertyName ) );
}
}
}
In the MainWindows you can assign and use the dataContext :
public partial class MainWindow : Window {
DC_Reservation dataContext {
get { return DataContext as DC_Reservation; }
}
private string message;
public MainWindow() {
InitializeComponent();
DataContext = new DC_Reservation();
}
protected void Create_Reservation_Click(object sender, RoutedEventArgs e) {
dataContext.PersonReservation = new Reservation();//Create a reservation instance
dataContext.PersonRoom = new Room(); //Create an instance of a room
dataContext.myPerson = new Person();//Create an instance of a person
CreateResRoom createReservationRoom = new CreateResRoom();//Create a instance of the CreateReservation WPF Form
// I'm not sure whether the next line is required.
createReservationRoom.DataContext = DataContext;
createReservationRoom.Show();
}
}
You can assign the DataContext in the constructor, but I think the better way is to define the DataContext in the MainWindow, in the other windows you can use the DesignContext:
<Window.DataContext>
<local:DC_Reservation />
</Window.DataContext>
So you can use the same DataContext over all forms ...
With DataBindings you can bind the input to the field:
<TextBox Text="{Binding FirstName, Path=myPerson, Mode=TwoWay}" />
I found another answer that Zarathos posted Jan 16 '13 at 21:43
for a different question
Use a public static class and access it from anywhere.
public static class Globals
{
public static String s_Name = "Mike"; //Modifiable in Code
public const int32 VALUE = 10; // unmodifiable
}
Then you can use it anywhere, provided you are working on the same namespace
string name = Globals.s_Name;

How can I change label text in different class (C#)

Please, you can you help me, how can i change label text in diferent class?
Basic winform script:
public partial class buildEditor : Form
{
public buildEditor()
{
InitializeComponent();
Label maxSkillPoint = new Label();
maxSkillPoint.AutoSize = true;
maxSkillPoint.BackColor = System.Drawing.Color.Transparent;
maxSkillPoint.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
maxSkillPoint.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(193)))), ((int)(((byte)(196)))), ((int)(((byte)(181)))));
maxSkillPoint.Location = new System.Drawing.Point(528, 687);
maxSkillPoint.Name = "maxSkillPoint";
maxSkillPoint.Text = UniqueValue.spentSkillPoints.ToString();
maxSkillPoint.Size = new System.Drawing.Size(0, 20);
this.Controls.Add(maxSkillPoint);
}
public void maxSkillPoint_TextChanged(Form formInstance, string labelName)
{
// Get reference to the label
var label = formInstance.Controls.Find(labelName, true).FirstOrDefault();
if (null != label && label is Label)
{
(label as Label).Text = "test";
}
}
}
I created next class which will be change text for maxSkill text.
public class ChangeTextForMaxSkill()
{
Button button = new Button();
public ChangeTextForMaxSkill()
{
button.Click += new EventHandler(changeText);
}
private void changeText(object sender, EventArgs e)
{
// Get reference to the label
var buildEditor = new buildEditor();
buildEditor.maxSkillPoint_TextChanged(buildEditor, "maxSkillPoint");
}
}
I really thx for all answers.
I got it very simple:
Hand over the Label control in the constructor of your external class:
using System.Windows.Forms;
public class Yourclass{
private Label UpdateLabel;
public Yourclass (Label yourLabel)
{
this.UpdateLabel = yourlabel;
}
private void action()
{
//here is your update of the label
UpdateLabel.Text = "Your text";
}
}
In the form class, create an instance of "yourclass" and hand over the Label:
Yourclass cls = new Yourclass(Label1);
First of all your naming conventions do not follow standard practices. Both class and method names should use uppercase first letters of words, not camel case as you have done. I have used proper naming conventions in my answer.
You have to pass an instance of your BuildEditor* form to your ChangeTextForMaxSkill.ChangeText() function.
Next, the label object maxSkill is not a property of your BuildEditor class. Therefore, you'd need to actually find a reference to that control within the form since you're dynamically adding it.
public partial class BuildEditor : Form
{
public BuildEditor()
{
InitializeComponent();
Label maxSkill = new Label();
maxSkill.Name = "MaxSkil"; // need the ID to find it later (makes it easier)
maxSkill.Location = new Point(1, 1);
this.Controls.Add(maxSkill);
}
// This is just for testing; assumes you dragged a button from toolbox onto your
// BuildEditor form in the Form Designer
private void button1_Click(object sender, EventArgs e)
{
var changeTextForMaxSkill = new ChangeTextForMaxSkill();
changeTextForMaxSkill.ChangeText(this, "MaxSkil");
}
}
public class ChangeTextForMaxSkill
{
public void ChangeText(Form formInstance, string labelName)
{
// Get reference to the label
var label = formInstance.Controls.Find(labelName, true).FirstOrDefault();
if (null != label && label is Label)
{
(label as Label) .Text = "test";
}
}
}
If you want to test it, just add a button on your form and make the test in the button click handler:
private void button1_Click(object sender, EventArgs e)
{
var changeTextForMaxSkill = new ChangeTextForMaxSkill();
changeTextForMaxSkill.ChangeText(this, "MaxSkil");
}
I've tested and this works :)

I have a context problem with c#

I have a problem with 2 Windows Forms which I created in c#. The first form (menu) has a PrintPreviewDialog object. The "menu" form then instantiates a copy of the send class "file" and call a ShopDialog method.
The "file" class write a file and calls a method (direct) in the "menu" class.
The problem I have is that the "direct" method is not known to the "menu" class. I think the answer is to define a copy of "menu" class in the "file", but I can't see have to do that.
Thanks for any help in advance.
John
namespace CSharp
{
public partial class MainMenu : Form
{
// Fields for printing.
public PrintDocument printDocument1 = new PrintDocument();
PageSettings printPageSettings = new PageSettings();
static RichTextBox printRichTextBox = new RichTextBox();
static string stringToPrint = "";
Font printFont = new Font("Arial", 10);
/****************************************************
* Select the Data->File-IO menu item. *
****************************************************/
private void fileIoToolStripMenuItem1_Click(object sender, EventArgs e)
{
File_IO fileIoDialog = new File_IO();
fileIoDialog.ShowDialog();
}
/****************************************************
* Initiate the printing process. The data to be *
* printed will be read from a file and stored in a*
* rich text box. The print menu buttons are *
* enabled. *
****************************************************/
public static void PrintInitialise(String printSource)
{
try
{
// Read text file and load into printRichTextBox.
FileStream printStream = new FileStream(printSource, FileMode.Open, FileAccess.Read);
printRichTextBox.LoadFile(printSource, RichTextBoxStreamType.PlainText);
printStream.Close();
// Initialise string to print.
stringToPrint = printRichTextBox.Text;
}
catch (Exception ex)
{
// Display error message if they appear.
MessageBox.Show(ex.Message);
}
}
/****************************************************
* Select the Data->File-IO menu item. *
****************************************************/
public void PrintDirect()
{
printDocument1.Print();
}
/****************************************************
* Select the Data->File-IO menu item. *
****************************************************/
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int numChars;
int numLines;
string stringForPage;
StringFormat strFormat = new StringFormat();
// Based on page setup, define drawable rectangle on page
}
}
}
namespace `enter code here`CSharp
{
public partial class File_IO : Form
{
MainMenu mainBransom;
public File_IO()
{
InitializeComponent();
}
private void btnPrint_Click(object sender, EventArgs e)
{
MainMenu.PrintInitialise(printSource);
mainBransom.PrintDirect();
}
You could use a property to store a reference to the menu class in the send class.
public class send: Form
{
public send(Form menuForm)
{
menu = menuForm;
}
public Form menu { get; private set; }
//... some other methods and properties
public void SomeButton_Click(object sender, EventArgs e)
{
// you have access to the direct method (provided it is public)
menu.direct();
}
}
In order to instantiate the send class you need to pass a reference to the menu form.

Categories