In the given code. I want to access the private value in the other main class I read the value from the console and through this class want to display in the console
using System;
class Customer
{
private string _customerAddress;
public string CustomerAddress
{
get { return this._customerAddress; }
set { this._customerAddress = value; }
}
public void DisplayDetails()
{
Console.WriteLine("Hello World", CustomerAddress);
}
}
I'm not sure what you mean, but if you want to give '_customerAddress' a value in your main form and then display the value with the 'DisplayDetails()' method then the following might help.
Main Form ==> make an Customer object and then give _customerAddress a value by simple doing this:
Customer customer = new Customer();
customer.CustomerAddress = "test";
customer.DisplayDetails();
You should also consider to give '_customerAddress' as a parameter in the constructor.
In case you want to acces a private field from another class and display it in this class, then you should do the following:
Step1: make a property in the other class like you did in the Customer class.
Step 2: Make a another Display function and give to its parameter the object of the other class.
public class OtherClass
{
private string message;
public string Message
{
get{return this.message;}
set{this.message = value;}
}
}
call the property in your Customer Class:
class Customer
{
private string _customerAddress;
public string CustomerAddress
{
get { return this._customerAddress; }
set { this._customerAddress = value; }
}
public void DisplayDetails()
{
Console.WriteLine("Hello World", CustomerAddress);
}
public void DisplayMessage(OtherClass otherClass)
{
Console.WriteLine("Hello World",otherClass.Message);
}
}
You can also make the method dat displays the message in the OtherClass Class and call that method in your Customer Class.
I can't seem to find out the answer to this through searching, so here goes....
I know that I can pass Class objects generically to other classes by utilising this type of code:
public class ClsGeneric<TObject> where TObject : class
{
public TObject GenericType { get; set; }
}
Then constructing in this way:
ClsGeneric<MyType> someName = new ClsGeneric<MyType>()
However, I have an application that requires me to open a Form and somehow pass in the generic type for use in that form. I am trying to be able to re-use this form for many different Class types.
Does anyone know if that's possible and if so how?
I've experimented a bit with the Form constructor, but to no avail.
Many thanks in advance,
Dave
UPDATED: A Clarification on what the outcome I am trying to achieve is
UPDATED: 4th AUG, I've moved on a little further, but I offer a bounty for the solution. Here is what I have now:
interface IFormInterface
{
DialogResult ShowDialog();
}
public class FormInterface<TObject> : SubForm, IFormInterface where TObject : class
{ }
public partial class Form1 : Form
{
private FormController<Parent> _formController;
public Form1()
{
InitializeComponent();
_formController = new FormController<Parent>(this.btnShowSubForm, new DataController<Parent>(new MeContext()));
}
}
public class FormController<TObject> where TObject : class
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
showSubForm("Something");
}
public void showSubForm(string className)
{
//I'm still stuck here because I have to tell the interface the Name of the Class "Child", I want to pass <TObject> here.
// Want to pass in the true Class name to FormController from the MainForm only, and from then on, it's generic.
IFormInterface f2 = new FormInterface<Child>();
f2.ShowDialog();
}
}
class MeContext : DbContext
{
public MeContext() : base(#"data source=HAZEL-PC\HAZEL_SQL;initial catalog=MCL;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework") { }
public DbSet<Parent> Child { get; set; }
}
public class DataController<TObject> where TObject : class
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class Parent
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child
{
string Name { get; set; }
int Age { get; set; }
}
Maybe you've tried this, but you can create a custom class:
public class GenericForm<TObject> : Form where TObject : class
{
// Here you can do whatever you want,
// exactly like the example code in the
// first lines of your question
public TObject GenericType { get; set; }
public GenericForm()
{
// To show that this actually works,
// I'll handle the Paint event, because
// it is executed AFTER the window is shown.
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
// Let's print the type of TObject to see if it worked:
MessageBox.Show(typeof(TObject).ToString());
}
}
If you create an instance of it like that:
var form = new GenericForm<string>();
form.Show();
The result is:
Going further, you can create an instance of type TObject from within the GenericForm class, using the Activator class:
GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
In this example, since we know that is a string, we also know that it should throw an exception because string does not have a parameterless constructor. So, let's use the char array (char[]) constructor instead:
GenericType = (TObject)Activator.
CreateInstance(typeof(TObject), new char[] { 'T', 'e', 's', 't' });
MessageBox.Show(GenericType as string);
The result:
Let's do the homework then. The following code should achieve what you want to do.
public class Parent
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child
{
string Name { get; set; }
int Age { get; set; }
}
public class DataController<TObject> where TObject : class
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class FormController<TObject> where TObject : class
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
GenericForm<TObject> form = new GenericForm<TObject>();
form.ShowDialog();
}
}
public class GenericForm<TObject> : Form where TObject : class
{
public TObject GenericType { get; set; }
public GenericForm()
{
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
MessageBox.Show(typeof(TObject).ToString());
// If you want to instantiate:
GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
}
}
However, looking to your current example, you have two classes, Parent and Child. If I understand correctly, those are the only possibilities to be the type of TObject.
If that is the case, then the above code will explode if someone pass a string as the type parameter (when the execution reaches Activator.CreateInstance) - with a runtime exception (because string does not have a parameterless constructor):
To protect your code against that, we can inherit an interface in the possible classes. This will result in a compile time exception, which is preferable:
The code is as follows.
// Maybe you should give a better name to this...
public interface IAllowedParamType { }
// Inherit all the possible classes with that
public class Parent : IAllowedParamType
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child : IAllowedParamType
{
string Name { get; set; }
int Age { get; set; }
}
// Filter the interface on the 'where'
public class DataController<TObject> where TObject : class, IAllowedParamType
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class FormController<TObject> where TObject : class, IAllowedParamType
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
GenericForm<TObject> form = new GenericForm<TObject>();
form.ShowDialog();
}
}
public class GenericForm<TObject> : Form where TObject : class, IAllowedParamType
{
public TObject GenericType { get; set; }
public GenericForm()
{
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
MessageBox.Show(typeof(TObject).ToString());
// If you want to instantiate:
GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
}
}
UPDATE
As RupertMorrish noted, you can still compile the following code:
public class MyObj : IAllowedParamType
{
public int Id { get; set; }
public MyObj(int id)
{
Id = id;
}
}
And that should still rise an exception, because you just removed the implicit parameterless constructor. Of course, if you know what you are doing, this is hard to happen, however we can forbidden this by using new() on the 'where' type filtering - while also getting rid of the Activator.CreateInstance stuff.
The entire code:
// Maybe you should give a better name to this...
public interface IAllowedParamType { }
// Inherit all the possible classes with that
public class Parent : IAllowedParamType
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child : IAllowedParamType
{
string Name { get; set; }
int Age { get; set; }
}
// Filter the interface on the 'where'
public class DataController<TObject> where TObject : new(), IAllowedParamType
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class FormController<TObject> where TObject : new(), IAllowedParamType
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
GenericForm<TObject> form = new GenericForm<TObject>();
form.ShowDialog();
}
}
public class GenericForm<TObject> : Form where TObject : new(), IAllowedParamType
{
public TObject GenericType { get; set; }
public GenericForm()
{
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
MessageBox.Show(typeof(TObject).ToString());
// If you want to instantiate:
GenericType = new TObject();
}
}
I think you can add a new type argument to FormController:
public class FormController<TParent, TChild>
where TParent : class
where TChild : class
{
...
public void showSubForm(string className)
{
IFormInterface f2 = new FormInterface<TChild>();
f2.ShowDialog();
}
}
So as I understand it, you want a Form<T> to open upon some action in the MainForm, with your MainForm using a FormController, as a manager of all your forms, relaying the generic type information to your Form<T>. Furthermore, the instantiated object of your Form<T> class should request an instance of a DatabaseController<T> class from your FormController.
If that is the case, the following attempt might work:
MainForm receives a reference to the FormController instance upon constructor initialization or has another way to interact with the FormController, e.g. a CommonService of which both know, etc.
This allows MainForm to call a generic method of the FormController to create and show a new Form object:
void FormController.CreateForm<T> ()
{
Form<T> form = new Form<T>();
form.Show();
// Set potential Controller states if not stateless
// Register forms, etc.
}
with Form<T> along the lines of:
class Form<T> : Form where T : class
{
DatabaseController<T> _dbController;
Form(FormController formController)
{
_dbController = formController.CreateDatabaseController<T>();
}
}
Now you have a couple of ways for the Form to receive a DatabaseController instance:
1. Your Form<T> receives a reference of the FormController or has another way to communicate with it to call a method along the lines of:
DatabaseController<T> FormController.CreateDatabaseController<T> ()
{
return new DatabaseController<T>();
}
Your FormController does not need to be generic, otherwise you'd need a new FormController instance for every T there is. It just needs to supply a generic method.
Your Form<T> receives an instance of the DatabaseController from the FormController upon constructor initialization:
void FormController.CreateForm ()
{
Form form = new Form(new DatabaseController());
form.Show();
}
with Form<T> being:
class Form<T> : Form where T : class
{
DatabaseController<T> _dbController;
Form(DatabaseController<T> controller)
{
_dbController = controller;
}
}
3. Like with 2 but your Form<T> and DatabaseController<T> provide static FactoryMethods to stay true to the Single Responsibility Priciple. e.g.:
public class Form<T> : Form where T : class
{
private DatabaseController<T> _dbController;
public static Form<T> Create<T>(DatabaseController<T> controller)
{
return new Form<T>(controller);
}
private Form(DatabaseController<T> controller)
{
_dbController = controller;
}
}
4. You can also use an IoC Container to register and receive instances of a specific type at runtime. Every Form<T> receives an instance of the IoC Container at runtime and requests its corresponding DatabaseController<T>. This allows you to better manage the lifetime of your controller and form objects within the application.
Well i'm not gonna go into the details here and will only suffice to some blueprints.
In this scenario i'd use a combination of Unity constructor injection with a generic factory to handle the instantiation given the type in main form.
It's not that intricate, take a look at Unity documentation at
Dependency Injection with Unity
The reason for picking Unity out of all DI containers is it was part of Enterprise Library from Microsoft itself and now continues to live on as an independent library in the form of Nugget. a friend of mine has recently ported Unity to .Net core, too. Simply put, it's hands down the most elaborate container available.
As for the factory i believe it's necessary because you don't wanna create a concrete lookup for handling all possible types, so it clearly has to be a generic factory. I'd advise you to make your factory a singleton and put it in whole another project, thereby separating your UI project from the models and both party will communicate through this DI bridge. you can even take a step further and process your model types using assembly reflection.
sorry for being too general, but i really don't know how familiar are you with these patterns. It really worth taking some time and utilizing these patterns. in my humble opinion there is no escape from these maneuvers if you want a truly scalable software.
You can reach me in private if you're looking for hints on implementation of any of the above-mentioned strategies.
Try Factory method.
public interface IProvider
{
T GetObject<T>();
}
Top-level form:
public class TopLevelForm : Form
{
public TopLevelForm(IProvider provider):base()
{
_provider = provider;
}
private void ShowSecondForm()
{
var f2 = new SecondForm(provider);
f2.Show();
}
}
Second-level form:
public class SecondLevelForm : Form
{
public SecondLevelForm(IProvider provider):base()
{
_data = provider.GetObject<MyEntity>();
}
}
As for IProvider's implementation - there are plenty of methods, starting from the simpliest one, return new T();
I made a class which requires the public default constructor but
that is never called; instead another constructor is used at DataGrid.AddingNewItem.
I'd like to tell developers that the default constructor is not for their use.
Is there an attribute which suits the purpose?
I had checked DebuggerNonUserCode and MethodImplAttribute with MethodImplAttributes.InternalCall but not sure that's the proper approach.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.dataGrid1.CanUserAddRows = true;
var list = new List<RowX>();
this.dataGrid1.ItemsSource = CollectionViewSource.GetDefaultView(list);
this.dataGrid1.AddingNewItem += (s, e) => e.NewItem = new RowX("ABC");
}
}
public class RowX
{
public RowX()
{
//this is not used. but CollectionView require this to be public or
//CanUserAddRows doesn't work.
}
public RowX(object o)
{
//this is the actual ctor.
}
public string Text { get; set; }
}
Mark it private
class Foo
{
private Foo() {}
}
You can give your constructor an access modifier.
private This means it can only be called from another constructor in that class.
public class PrivateClass
{
//Only from inside this class:
private PrivateClass()
{
}
public static PrivateClass GetPrivateClass()
{
//This calls the private constructor so you can control exactly what happens
return new PrivateClass();
}
}
internal This means only code in the same assembly (i.e. from inside your library) can access it.
public class InternalClass
{
//Only from within the same assembly
internal InternalClass(string foo)
{
}
}
I know this has been asked thousands of time but still after a lot of research I can't find a solution and I am really sorry about this post.
I want to access my Label from a class in another namespace.
This is a sample of code to understand better what I am trying to do:
public partial class Main : Form
{
public Main()
{
InitializeComponent();
}
}
//class in another namespace
class Servers
{
public void _SetlabelText()
{
Main.label1.Text = "New Text";
}
}
How am I supposed to do it the proper way?
One option is to store a reference to the form in the constructor like this:
public class Servers
{
private Form _frmMain;
public Servers(Form frmMain)
{
_frmMain = frmMain;
}
public void SetlabelText()
{
_frmMain.label1.Text = "New Text";
}
}
And use it like this:
public partial class Main : Form
{
public Main()
{
InitializeComponent();
var servers = new Servers(this);
servers.SetlabelText();
}
}
However, it's typically advised to return back to the Form class and set it there, like this:
public partial class Main : Form
{
public Main()
{
InitializeComponent();
label1.Text = Servers.GetTextForLabel();
}
}
public class Servers
{
public static string GetTextForLabel()
{
return "New Text"; //(I assume this will be much more complex)
}
}
I've searched Google all day and can't find the correct answer to my issue, hoping someone here can help me.
So, in the "Main" form I have the method to show a form that needs to be centered directly above the parent form (frmMain). Normally I would call ShowDialog(this) to see the parent, but for some reason I have to set the loadNewsFeedItem to static in order to see the method from the flpNewsFeedHeader : Label derrived class (below). The OnClick event triggers the method loadNewsFeedItem().
When I call this to set the parent, I'm getting the message "Keyword 'this' is not valid in a static property, static method, or static field initializer"
namespace NewsFeeds
{
public partial class FrmMain : Form
{
public static void loadNewsFeedItem()
{
frmNewsFeedView frmFeedView = new frmNewsFeedView(FrmFuncs.selFeedID);
frmFeedView.ShowDialog(this); // Error occurs on this line, when calling this via a static method
}
}
}
public class flpNewsFeedHeader : Label
{
private int FeedID = 0;
public int theFeedID
{
get { return FeedID; }
set { FeedID = value; }
}
protected override void OnClick(EventArgs e)
{
FrmFuncs.selFeedID = FeedID;
Thread thrShowFeed = new Thread(new ThreadStart(FrmMain.loadNewsFeedItem));
thrShowFeed.Start();
}
}
Can someone please give me a corrected code example or a hint as to how to get the loadNewsFeedItem() to be visible without setting the accessor to static, or how to work around this in a static accessor?
Thanks in advance!
Chris
Edit: used ActiveForm for owner.
public partial class FrmMain : Form
{
public static void loadNewsFeedItem(Form owner)
{
frmNewsFeedView frmFeedView = new frmNewsFeedView(FrmFuncs.selFeedID);
frmFeedView.ShowDialog(owner);
}
}
}
public class flpNewsFeedHeader : Label
{
private int FeedID = 0;
public int theFeedID
{
get { return FeedID; }
set { FeedID = value; }
}
protected override void OnClick(EventArgs e)
{
FrmFuncs.selFeedID = FeedID;
// Shouldn't need a new thread. Already on the GUI thread.
FrmMain.loadNewsFeedItem (System.Windows.Forms.Form.ActiveForm);
}
}
may be you mean this:
frmFeedView.Owner = System.Windows.Forms.Form.ActiveForm;
frmFeedView.ShowDialog();
In a static method, this is meaningless. One option is to skip the parameter
frmFeedView.ShowDialog();
The other option is to setup a static variable as shown below (but beware, it can have side effects if you try to open multiple instances of FrmMain)
public partial class FrmMain : Form
{
private static FrmMain staticInstance;
public FrmMain()
{
staticInstance = this;
InitializeComponent();
...
}
public static void loadNewsFeedItem()
{
frmNewsFeedView frmFeedView = new frmNewsFeedView(FrmFuncs.selFeedID);
frmFeedView.ShowDialog(staticInstance );
}