How get determined buttons from class - c#

this is not long story!! just it seems to be long ;)
in my app I have user access, it means access to a button relate to its user access scope.
in winform layer: I have a form, it shows all of the determined buttons' name in partitioned checkedListboxes. I dont want fill the form manually. I want create checkedListboxes by code. to get their items'text, I have below planing:
clssMenu_Item: I can save name and text property of one button in this class.
public class clssMenu_Item
{
public string name;
public string text;
}
clssMenu_List: it give me 2D generic List<clssMenu_Item>. all of the buttons in one form will be in a object of this class.
public class clssMenu_List
{
public clssMenu_List ()
{
// I dont know how fill private variables
}
#region private variables
private List<clssMenu_Item> _main ; // buttons in main form
private List<clssMenu_Item> _accountancy; //buttons in accountancy form
private List<clssMenu_Item> _management; //buttons in management form
#endregion
#region public properties
public List<clssMenu_Item> main
{ get { return _main; } }
public List<clssMenu_Item> accountancy
{ get { return _accountancy; } }
public List<clssMenu_Item> management
{ get { return _management; } }
#endregion
}
the buttons in each forms have a common character in their Name property. For example all of the determined buttons in Main form are started with ''Mbtn'', so there isn't any same buttons' Name between forms.
now I dont know how fill private variables in clssMenu_List. then I could use it in my facade layer.
thanks for your attention my friend!! please help me to solve it

I would create a separated helper class that extracts all buttons from a form.
public static class FormHelper
{
public static Button[] GetButtonsFromForm(Form form)
{
// ...
}
}
I would create properties instead of fields:
public class clssMenu_Item
{
public string Name {get;set;}
public string Text {get;set;}
}
A method to create menu_items:
public IEnumerable<clssMenu_Item> GetMenuItemsFromForm(Form form)
{
// convert the buttons to menu_items
return from button in FormHelper.GetButtonsFromForm(form);
select new clssMenu_Item { Name = button.Name, Text = button.Text };
}
Next I would add all buttons to the right list.
public void Fill()
{
clssMenu_List lst = new clssMenu_List();
clssMenu_List.main.AddRange(GetMenuItemsFromForm(mainForm));
clssMenu_List.accountancy.AddRange(GetMenuItemsFromForm(accountancyForm));
clssMenu_List.management.AddRange(GetMenuItemsFromForm(managementForm));
}
Don't forget to create the list in you class:
private List<clssMenu_Item> _main = new List<classMenu_Item>(); // buttons in main form
private List<clssMenu_Item> _accountancy = new List<classMenu_Item>(); //buttons in accountancy form
private List<clssMenu_Item> _management = new List<classMenu_Item>(); //buttons in management form
Personally:
I would store them in a dictionary because you can access them by name. And I would not create properties of List-types. I'd rather create Add/Remove methods.

Related

How do i specify that i want to change a label on a particular form? [duplicate]

I have a winform called Form1 and a textbox called textBox1
In the Form1 I can set the text by typing:
textBox1.text = "change text";
Now I have created another class. How do I call textBox1 in this class?
so I want to change the text for textBox1 in this class.
How can I access the Form1 from this new class?
I would recommend that you don't. Do you really want to have a class that is dependent on how the text editing is implemented in the form, or do you want a mechanism allowing you to get and set the text?
I would suggest the latter. So in your form, create a property that wraps the Text property of the TextBox control in question:
public string FirstName
{
get { return firstNameTextBox.Text; }
set { firstNameTextBox.Text = value; }
}
Next, create some mechanism through which you class can get a reference to the form (through the contructor for instance). Then that class can use the property to access and modify the text:
class SomeClass
{
private readonly YourFormClass form;
public SomeClass(YourFormClass form)
{
this.form = form;
}
private void SomeMethodDoingStuffWithText()
{
string firstName = form.FirstName;
form.FirstName = "some name";
}
}
An even better solution would be to define the possible interactions in an interface, and let that interface be the contract between your form and the other class. That way the class is completely decoupled from the form, and can use anyting implementing the interface (which opens the door for far easier testing):
interface IYourForm
{
string FirstName { get; set; }
}
In your form class:
class YourFormClass : Form, IYourForm
{
// lots of other code here
public string FirstName
{
get { return firstNameTextBox.Text; }
set { firstNameTextBox.Text = value; }
}
}
...and the class:
class SomeClass
{
private readonly IYourForm form;
public SomeClass(IYourForm form)
{
this.form = form;
}
// and so on
}
I was also facing the same problem where I was not able to appendText to richTextBox of Form class. So I created a method called update, where I used to pass a message from Class1.
class: Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
_Form1 = this;
}
public static Form1 _Form1;
public void update(string message)
{
textBox1.Text = message;
}
private void Form1_Load(object sender, EventArgs e)
{
Class1 sample = new Class1();
}
}
class: Class1.cs
public class Class1
{
public Class1()
{
Form1._Form1.update("change text");
}
}
You can change the access modifier for the generated field in Form1.Designer.cs from private to public. Change this
private System.Windows.Forms.TextBox textBox1;
by this
public System.Windows.Forms.TextBox textBox1;
You can now handle it using a reference of the form Form1.textBox1.
Visual Studio will not overwrite this if you make any changes to the control properties, unless you delete it and recreate it.
You can also chane it from the UI if you are not confortable with editing code directly. Look for the Modifiers property:
public partial class Form1 : Form
{
public static Form1 gui;
public Form1()
{
InitializeComponent();
gui = this;
}
public void WriteLog(string log)
{
this.Invoke(new Action(() => { txtbx_test1.Text += log; }));
}
}
public class SomeAnotherClass
{
public void Test()
{
Form1.gui.WriteLog("1234");
}
}
I like this solution.
You will need to have some access to the Form's Instance to access its Controls collection and thereby changing the Text Box's Text.
One of ways could be that You can have a Your Form's Instance Available as Public or More better Create a new Constructor For your Second Form and have it receive the Form1's instance during initialization.
Define a property of the form like, then use this in other places it would be available with the form instance
public string SetText
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
If your other class inherits Form1 and if your textBox1 is declared public, then you can access that text box from your other class by simply calling:
otherClassInstance.textBox1.Text = "hello world";
Use, a global variable or property for assigning the value to the textbox, give the value for the variable in another class and assign it to the textbox.text in form class.
I Found an easy way to do this,I've tested it,it works Properly.
First I created a Windows Project,on the form I Inserted a TextBox and I named it textBox1
then I inserted a button named button1,then add a class named class1.
in the class1 I created a TextBox:
class class1
{
public static TextBox txt1=new TextBox(); //a global textbox to interfece with form1
public static void Hello()
{
txt1.Text="Hello";
}
}
Now in your Form Do this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
class1.txt1=textBox1;
class1.Hello();
}
}
in the button1_Click I coppied the object textBox1 into txt1,so now txt1 has the properties
of textBox1 and u can change textBox1 text in another form or class.
Form1 form = new Form1();
form.textBox1.Text = "test";
I tried the examples above, but none worked as described. However, I have a solution that is combined from some of the examples:
public static Form1 gui;
public Form1()
{
InitializeComponent();
gui = this;
comms = new Comms();
}
public Comms()
{
Form1.gui.tsStatus.Text = "test";
Form1.gui.addLogLine("Hello from Comms class");
Form1.gui.bn_connect.Text = "Comms";
}
This works so long as you're not using threads. Using threads would require more code and was not needed for my task.
I used this method for updating a label but you could easily change it to a textbox:
Class:
public Class1
{
public Form_Class formToOutput;
public Class1(Form_Class f){
formToOutput = f;
}
// Then call this method and pass whatever string
private void Write(string s)
{
formToOutput.MethodToBeCalledByClass(s);
}
}
Form methods that will do the updating:
public Form_Class{
// Methods that will do the updating
public void MethodToBeCalledByClass(string messageToSend)
{
if (InvokeRequired) {
Invoke(new OutputDelegate(UpdateText),messageToSend);
}
}
public delegate void OutputDelegate(string messageToSend);
public void UpdateText(string messageToSend)
{
label1.Text = messageToSend;
}
}
Finally
Just pass the form through the constructor:
Class1 c = new Class1(this);
Form frm1 = new Form1();
frm1.Controls.Find("control_name",true)[0].Text = "I changed this from another form";
// Take the Active form to a form variable.
Form F1 = myForm1.ActiveForm;
//Findout the Conntrol and Change the properties
F1.Controls.Find("Textbox1", true).ElementAt(0).Text= "Whatever you want to write";
What about
Form1.textBox1.text = "change text";
note:
1. you have to "include" Form1 to your second form source file by
using Form1;
textBox1 should be public

Passing data from textbox to datagridview

I am working in Visual Studio running a Windows application.
I am wondering if I can fill a DataGridView from a TextBox, that was a passed value itself?
For example, the user would search for a patient from a dialog form. The patient's name they select would populate a TextBox on my main form. I want that selected patients prior test history to populate a DataGridView on that main form within a tab.
Is this possible, if so how would I accomplish this?
It is possible. I would suggest setting up some sort of data binding. More specifically you will want some class that maintains state and data binds to your controls and possibly your dialog form. I don't know how much you are looking for so this might be going overboard but I would suggest something like this:
public class MainForm : Form
{
public MainForm(StateManager stateManager)
{
_stateManager = stateManager;
//data binding for your text box
txtPatientName.DataBindings.Add(nameof(txtPatientName.Text), stateManager, nameof(stateManager.PatientName));
//data binding for your grid
historyGrid.DataSource = stateManager.History;
}
private void btnShowForm_Click(object sender, EventArgs e)
{
using(var form = new DialogForm())
{
var result = form.ShowDialog();
if(result == DialogResult.Ok)
{
_stateManager.UpdatePatient(form.InputPatientName);
}
}
}
private StateManager _stateManager;
}
//this is the form where you enter the patient name
public class DialogForm : Form
{
//this holds the value where the patient's name is entered on the form
public string InputPatientName { get; set; }
}
//this class maintains your state
public class StateManager : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string PatientName
{
get { return _patientName; }
set
{
_patientName = value;
OnPropertyChanged(nameof(PatientName));
}
}
public BindingList<MedicalHistoryItems> History => _history ?? (_history = new BindingList<MedicalHistoryItems>());
public void UpdatePatient(string patientName)
{
History.Clear();
var historyRetriever = new HistoryRetriever();
History.AddRange(historyRetriever.RetrieveHistory(patientName));
}
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(propertyName);
}
private BindingList<MedicalHistoryItems> _history;
private string _patientName;
}

Button located under tabitem (within tabcontrol) but the handler needs to be in the main window

I have a main windows, which contains some controls including a tabcontrol. The tab control itself has multiple tabitems. Each tab item has a unique design. When the user clicks a button within one of the tab items, I want the event handler to be within the main window's .cs file. I cant figure out a way to do that, can any one enlighten me?
My syntax may not be perfect, but what about this:
public interface ITabControlWithNotifications
{
void OnButtonClicked(...);
}
public sealed class TabControlWithNotifications : TabControl, ITabControlWithNotifications
{
public void OnButtonClicked(...)
{
...
}
}
public sealed class TabPageWithNotifications : TabPage
{
private readonly ITabControlWithNotifications parentTabControl;
public TabPageWithNotifications(ITabControlWithNotifications tabControlWithNotifications)
{
this.parentTabControl = tabControlWithNotifications;
this.InitialzeComponents();
}
... ClickEventHandler(...)
{
this.parentTabControl.OnButtonClicked(...);
}
}
public sealed class TabControlFactory
{
public void Build()
{
var parentTabControl = new TabControlWithNotifications();
var tabPage1 = new TabPageWithNotifications(parentTabControl);
var tabPage2 = new TabPageWithNotifications(parentTabControl);
var tabPage3 = new TabPageWithNotifications(parentTabControl);
parentTabControl.Controls.Add(tabPage1);
parentTabControl.Controls.Add(tabPage2);
parentTabControl.Controls.Add(tabPage3);
}
}

C# Passing values from one form to another open form

I am learning the C# programming language and am making a Payroll program addon for SAP Business One. I have two forms and I want to pass a value from PayrollFormulaBuilder.cs to EarnDeductSetup.cs.
The PayrollFormulaBuilder is used by a user to generate a formula and is saved to a string. A user clicks on a calculator button on the EarnDeductSetup form in order to open up the PayrollFormulaBuilder form. The EarnDeductSetup form is still open but in the background. I want the generated formula to show on my EarnDeductSetup form (I have a textbox, txt_formula_template.Text) as soon as a user clicks on an 'Apply button on the PayrollFormulaBuilder form. i would also like for this PayrollFormulaBuilder form to close as soon as the apply button is pressed.
Right now, I am unable to show the generated formula on my EarnDeductSetup form
My Code: (EarnDeductSetupForm)
namespace EIM_Payroll_Application
{
public partial class EarnDeductSetupForm : Form
{
private SAPbobsCOM.Company company;
public string SAPCodePD { get; set; }
public EarnDeductSetupForm(SAPbobsCOM.Company co)
{
InitializeComponent();
this.company = co;
}
...
private void btn_calculator_Click(object sender, EventArgs e)
{
PayrollFormulaBuilder PC = new PayrollFormulaBuilder();
PC.ShowDialog();
}
...
if (rb_calculated_amt.Checked == true)
{
txt_formula_template.Text = SAPUtility._formulaVariable;
formulaTemplate = txt_formula_template.Text;
}
SAPUtility.cs
namespace Payroll.Util.Helpers
{
public static class SAPUtility
{
public static string _formulaVariable = String.Empty;
public static string variable
{
get { return _formulaVariable; }
set { _formulaVariable = value; }
}
...
PayrollFormulaBuilder.cs
private void btnApply_Click(object sender, EventArgs e)
{
SAPUtility._formulaVariable = formula_display.Text;
this.Close();
EarnDeductSetupForm.ActiveForm.ShowDialog();
}
My question is, how do I get this formula to show on my txt_formula_template.Text textbox on my EarnDeductSetupForm as soon as a user presses apply on the PayrollFormulaBuilder form?
Set the button in the parent form to internal, then use the parent or parentform property in the dialog to access it, by casting it to the parent for type (this should expose the internal button with intellisense). Call ShowDialog with "this" as parameter (no quotes).
Subscribe to events on the internal button the parent form, in the child dialog. And do your thing in the event handler.

C# Accessing controls from an outside class without "public"

I know this has been asked before but I believe my situation is a bit different -- or I don't understand the answers given. I have spent about 4 hours working on this solidly and finally realized, I just don't know what to do.
I have 2 Forms (Form1, Settings) and a class I created called Themes.
I have get/set properties that currently work but are all within Form1 and I would like to move as much code related to themeing as I can OUTSIDE of Form1 and into Themes.cs.
Changing Theme: To change the theme, the user opens up the Settings form and selects a theme from the dropdown menu and presses the 'Set' button -- this all works, but now I want to move it into my own class and I can't get the code to compile.
Here is example code that works before moving -- note that this is only 2 different controls I want to modify but there are about 30 total. I am abridging the code:
Form 1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnSettings_Click(object sender, EventArgs e)
{
Settings frm = new Settings(this);
frm.Show();
}
private Color txtRSSURLBGProperty;
private Color txtRSSURLFGProperty;
public Color TxtRSSURLBGProperty
{
get { return txtRSSURLBGProperty; }
set { txtRSSURL.BackColor = value; }
}
public Color TxtRSSURLFGProperty
{
get { return txtRSSURLFGProperty; }
set { txtRSSURL.ForeColor = value; }
}
Settings Form:
public partial class Settings : Form
{
public Settings()
{
InitializeComponent();
}
private Form1 rssReaderMain = null;
public Settings(Form requestingForm)
{
rssReaderMain = requestingForm as Form1;
InitializeComponent();
}
private void button2_Click(object sender, EventArgs args)
{
// Appearence settings for DEFAULT THEME
if (cbThemeSelect.SelectedIndex == 1)
{
this.rssReaderMain.TxtRSSURLBGProperty = Color.DarkSeaGreen;
this.rssReaderMain.TxtRSSURLFGProperty = Color.White;
[......about 25 more of these....]
}
The theme class is currently empty. Again, the goal is to move as much code into the themes class (specifically the get/set statements if at all possible!) and hopefully just use a method similar to this within the Settings form once the proper drowndown item is selected: SetTheme(Default);
I hope someone can help, and I hope I explained it right! I have been racking my brain and I need to have this done fairly soon! Much thanks in advance as I'm sure everyone says. I have teamviewer or logmein if someone wants to remote in -- that is just as easy.
I can also send my project as a zip if needed.
Thanks so much,
Kurt
Modified code for review:
Form1 form:
public partial class Form1 : ThemeableForm
{
public Form1()
{
InitializeComponent();
}
ThemeableForm form:
internal abstract class ThemeableForm : Form
{
private Color rssLabelBGProperty;
private Color rssLabelFGProperty;
public Color RssLabelBGProperty
{
get { return rssLabelBGProperty; }
set { lRSS.BackColor = value; }
}
public Color RssLabelFGProperty
{
get { return rssLabelFGProperty; }
set { lRSS.ForeColor = value; }
}
Settings form:
public Settings(ThemeableForm requestingForm)
{
rssReaderMain = requestingForm as ThemeableForm;
InitializeComponent();
}
private ThemeableForm rssReaderMain = null;
private void button2_Click(object sender, EventArgs args)
{
// Appearence settings for DEFAULT THEME
if (cbThemeSelect.SelectedIndex == 1)
{
this.rssReaderMain.LRSSBGProperty = Color.DarkSeaGreen;
this.rssReaderMain.LRSSFGProperty = Color.White;
}
Now the all the controls in my get/set (lRSS in the example code above) error out with does not exist in the current context. I also get the warning:
Warning 1The designer could not be shown for this file because none of
the classes within it can be designed. The designer inspected the
following classes in the file:
Form1 --- The base class 'RSSReader_BKRF.ThemeableForm' could not be
loaded. Ensure the assembly has been referenced and that all projects
have been built. 0 0
Let the Themes class be composed largely of data that changes when a theme changes: Color, Fonts, etc.
Let the Settings form choose a theme and write it out as the Default Theme. If this is WinForms, then you can just have a static CurrentTheme property of the Themes class which returns the theme chosen on the Settings form.
Let the Form1 and any other forms delegate some of their properties to the current theme:
private Color BackgroundColor
{
get {return Themes.CurrentTheme.BackgroundColor;}
}
private Color TextColor
{
get {return Themes.CurrentTheme.TextColor;}
}
You might then want to push these delegated properties up to a base form class, to be shared by multiple forms.
Ok, I see you are trying to make the Settings form manipulate the values of properties on several (many?) other forms.
One solution is to have every other form inherit from the same abstract class, let's call it ThemeableForm. Now you can define ThemeableForm to have all the common properties.
A short example:
internal abstract class ThemeableForm : Form {
private Color txtRSSURLBGProperty;
private Color txtRSSURLFGProperty;
public Color TxtRSSURLBGProperty
{
get { return txtRSSURLBGProperty; }
set { txtRSSURL.BackColor = value; }
}
public Color TxtRSSURLFGProperty
{
get { return txtRSSURLFGProperty; }
set { txtRSSURL.ForeColor = value; }
}
}
And declare Form1:
public class Form1 : ThemeableForm {
// custom stuff for Form1, no need to write the common properties
}
I declared it as "internal" because you might want to control who/how THemeableForm is inherited. But, you could make it public too. And Settings can work with a ThemeableForm:
public Settings(ThemeableForm requestingForm)
{
rssReaderMain = requestingForm as ThemeableForm;
InitializeComponent();
}
private ThemeableForm rssReaderMain = null;
private void button2_Click(object sender, EventArgs args) {
// Appearence settings for DEFAULT THEME
if (cbThemeSelect.SelectedIndex == 1)
{
this.rssReaderMain.TxtRSSURLBGProperty = Color.DarkSeaGreen;
this.rssReaderMain.TxtRSSURLFGProperty = Color.White;
[......about 25 more of these....]
}
}
So you don't need to copy any of the Settings code for each and every other form type.

Categories

Resources