I am creating an application with a lot of forms and the visual style required takes a lot time to be applied from the designer, so I created a class called Layout to apply these
property changes to every form on its Load() method.
class Layout : Form
{
public void ApplicarLayout(Form frm)
{
frm.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(30)))), ((int)(((byte)(30)))));
foreach (Control c in frm.Controls)
{
if (c is TextBox)
{
//Apply textBox Formatting
}
//Iterate through the controls in the form and add respective format
}
}
}
So far, so good. My plan was to then inherit this class from every form and just call the base.AplicarLayout() method.However, I get the error:
Inconsistent accessibility: base class 'EntityClub_.Layout' is less accessible than class 'EntityClub_.MainAdminWindow'
Here you can see how I do it.
public partial class MainAdminWindow : Layout
{
public MainAdminWindow()
{
InitializeComponent();
}
public void MainAdminWindow_Load(object sender, EventArgs e)
{
base.ApplicarLayout(this);//ERROR HERE
}
}
Do you know how can I do this using inheritance? I don't want to instance the class and I don't want to pollute each window´s code with the layout method.
Classes without an explicit access modifier (and aren't nested) are implied to be internal.
Therefore:
class Layout : Form
..is internal, whereas:
public partial class MainAdminWindow : Layout
..is public (because you've explicitly said so). Changing Layout's declaration to this solves the issue:
public class Layout : Form
Related
I'm trying to add a few extra base properties (somewhere) in my project so that every window I create will automatically inherit these properties.
E.g. each window will have a "block_count" based on the area of the window
For context, I'm using a WPF project.
Currently trying: I've created an abstract window class with my desired properties and then defined my MainWindow as one of these types to inherit the property and method...
But when coding in my MainWindow class I still can't access the property or method even though it should have inherited them? Where am I going wrong or what is the best way to add properties to all windows in my project?
My Abstract Window class
public abstract partial class AbWinDefiner : Window
{
private int _block_count;
private void get_block_count()
{
_block_count = Convert.ToInt32(Math.Floor(Width * Height / 32));
}
public AbWinDefiner()
{
InitializeComponent();
}
}
My Main Window class
public partial class MainWindow : AbWinDefiner
{
public MainWindow()
{
InitializeComponent();
}
}
Make it protected, not private
Basically I have 2 projects, a form and a user control.
I need both of them to be in different projects but the form need to refer to the user control as it is using the user control. And the user control will need to refer to the form as it is using one of the form class. When I add the second one because it need the , VS will complain circular dependency which is understandable. How do I solve this?
Logically the form should depend on the user control. You could create an interface to replace the form within the user control project, and then have the form implement that interface.
Example user control project;
public interface IForm
{
string MyString { get; }
}
public class MyUserControl : UserControl
{
public IForm Form { get; set; }
private void ShowMyString()
{
String myString = Form.MyString;
...
}
}
Example Form project
public class MyForm : Form, IForm
{
public MYString { get "My String Value"; }
}
I think the root cause of your problem is that you haven't separated your concerns between the form and the control properly.
Since you have a (somewhat generic) control, it shouldn't depend on the form. All of the logic of the control should reside within the control itself. The form should only black-box consume the control: add it, set public fields, call public methods, etc. anything else is a violation of encapsulation.
Sometimes, controls may need to know things about their parent form. In this case, I would suggest something as simple as adding a Parent field to the child control.
if you need something more specific from the form, you can always add an interface; the interface should only list those things that the control needs from the form. For example, if you need the size, you can add:
public interface IControlParent {
int Width { get; }
int Height { get; }
}
This way, you clearly see the dependencies (what the control needs from the parent), and if the parent type/contract changes, you don't need to do as much to change your control class.
You must sepárate your code, its never a good idea to have a reference to an application assembly, if you try to reuse it in the future, the applications exe should go with the control.
So, take the class from the form project and move it to the control project or create a library project, put the class on it and reference it from your control and your app projects.
You should use an event (delegate). Let's assume that inside your form project you created one class: Form1. And inside user control you defined UserControl1.
UserControl1 needs to instantiate and call a method from Form1:
public class Form1
{
public void Execute(string sMessage)
{
Console.WriteLine(sMessage);
Console.ReadLine();
}
}
UserControl1:
public class UserControl
{
public Func<object, object> oDel = null;
public void Execute()
{
oDel?.Invoke("HELLO WORLD!");
}
}
And from the class that instantiate UserControl, let's call it ParentClass:
public class ParentClass
{
public void Execute()
{
UserControl oUserControl = new UserControl();
oUserControl.oDel = Form1Action;
oUserControl.Execute();
}
public object Form1Action(object obj)
{
string sObj = Convert.ToString(obj);
Form1 oForm = new Form1();
oForm.Execute(sObj);
return null;
}
}
This approach gives the responsibility of handling an event to the high level class.
I would like to create my own user controls which implement more properties and methods than the ones given from .NET Framework. First of all I would like to have a custom UserControl class, which I would call MyUserControl and of course will inherit from UserControl:
public class MyUserControl : UserControl {
public MyUserControl() : base() {
}
...
}
After that I would like to have my own MyTestBox, which will inherit from TextBox.
public class MyTextBox : TextBox {
public MyTextBox() : base() {
}
...
}
My problem now is that I want MyTextBox to inherit from MyUserControl also, because I have properties and methods implemented there, that I need in MyTextBox also.
The only solution I could think of is to make MyTextBox inherit just from MyUserControl and not from TextBox, but add a TextBox in it in the constructor:
public class MyTextBox : MyUserControl {
public MyTextBox() : base() {
Add(new TextBox());
}
...
}
but then I would have to re-implement every single property and method of TextBox in MyTextBox. Is there a better way to achieve this?
Separate out all the common code into a separate class and use delegation to handle it.
ie. something like this:
public class MyUserControl : UserControl
{
private MyExtraControlCode _Extras;
public MyUserControl()
{
_Extras = new MyExtraControlCode(this);
}
public int GetInt32Value()
{
return _Extras.GetInt32Value();
}
}
public class MyTextBox : TextBox
{
private MyExtraControlCode _Extras;
public MyTextBox()
{
_Extras = new MyExtraControlCode(this);
}
public int GetInt32Value()
{
return _Extras.GetInt32Value();
}
}
or something similar.
Not as straightforward, but multiple inheritance is just not supported in .NET.
After looking at the problem in more detail, I finally reached to this conclusion: There are 3 ways to achieve what I want, but all of them require some extra implementation.
First of all multiple inheritance is not supported in C# .NET. In my case it would make things more complex anyway, because in MyTextBox I wanted in a way to be able to access custom properties/methods from both MyUserControl and TextBox. But both of these classes inherit from Component Class, so multiple inheritance (if it were possible) would mess thing up here. The question I asked myself is: What do you finally want to do? The answer is, that I simply want to be able to "extend" all my UserControls (or Components) in general (namely regarding all UserControls) and also specifically (namely regarding TextBox, Combobox, ListView, etc), so that when I create a MyTextBox object, I could do both:
myTextBox.MyUserControlStuff();
and
myTextBox.TextBoxStuff();
So here are my solutions:
1. Use extensions
and extend UserControl (or Component) class. In that case, I have:
public class MyTextBox : TextBox
{
public void MyTextBoxStuff()
{
...
}
}
public static class UserControlExtensions
{
public static void MyUserControlStuff(this UserControl control)
{
...
}
}
And MyTextBox can also do all UserControl stuff and TextBox stuff
Downside: every (specific) extension method applies to UserControl also.
2. Use an interface
public class MyTextBox : TextBox, IUserControlStuff
{
public void MyTextBoxStuff()
{
...
}
public void MyUserControlStuff()
{
...
}
}
public interface IUserControlStuff
{
public void MyUserControlStuff();
}
Downside: I will have to re-implement MyUserControlStuff each time again and again.
3. Use an "extra code" class and make it a member of each custom UserControl & MyUserControl (like #Mr.Karlsen suggested)
See the answer of #Mr.Karlsen for more details. I would say this is the best solution, but it has its downside
Downside: A little messy. A developer, new to my project would find it difficult to understand when seeing it for the first time. I would personally avoid it.
Finally I decided to go with the interface, because my UserControl properties/methods are specific to my needs so it wouldn't be good to extend UserControl with "specific" stuff. I have to write more code in my case and even re-write the same code while implementing my interface's methods, which I really hate. Anyway!!
I have two classes that I'd like to keep in separate files.
namespace GridSystem
{
public class Grid
{
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
}
namespace GridSystem
{
public class GridItem
{
public void InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
}
How do I ensure no other classes are allowed to call InformAddedToGrid?
I'm trying to emulate Actionscript namespaces, which can be used on a method, in place of public, private, internal, etc. It doesn't exactly protect the method, but forces an extra step of including the namespace before the method can be accessed. Is there an alternative approach to this in C#?
If GridItem itself can be hidden from the outside world as well I would consider putting GridItem inside Grid as a nested class. That way it won't be visible outside of the class
http://www.codeproject.com/Articles/20628/A-Tutorial-on-Nested-Classes-in-C
Not that you should do this, you should do what TGH suggests, have a public interface for GridItem, and have gridItem nested in Grid (then have a factory method on Grid to create Items and use partial Grid class to have them in separate files).
Because there isn't a way of having friend methods ( you can do friend classes through InternalsVisibleToAttribute )
You COULD do this ( but don't... )
public partial class Grid
{
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
public class GridItem
{
public void InformAddedToGrid()
{
if (new StackTrace().GetFrame(1).GetMethod().DeclaringType !=
typeof(Grid)) throw new Exception("Tantrum!");
Console.WriteLine("Grid called in...");
}
}
then
var g = new Grid();
g.AddItem(new GridItem()); // works
new GridItem().InformAddedToGrid(); // throws a tantrum...
A really ugly answer would be to make it private and use reflection.
Another ugly answer would be to make it throw an exception if the caller is wrong.
Both of these are much slower to execute than a normal call also.
I don't think there's a good answer. C# doesn't have friends.
IMHO the answer is simple: access modifiers are just there to remind the programmer of the intent of how public/private a class should be. Through reflection you can lift those barriers.
The usage you make of a class is all in your hands: if your class is meant to only be used in one place, make it so. If anything, if a class has a special way of being used, document it - put it in the XML comments.
That said, in this specific example I'd believe since the GridItem doesn't add itself to the grid, it's not its job to notify about it (what if "I've not been added to the grid"?). I think InformAddedToGrid belongs somewhere in your Grid class as a private method, where there's a concept of adding an item... assuming that's what AddItem(GridItem) really does.
You can do it as TGH suggested, with nested classes, except the other way around. Nest Grid within GridItem and make InformAddedToGrid private. Here I use a nested base class so the public API can remain the same. Note that no one outside of your assembly can inherit from GridBase because the constructor is internal.
public class GridItem
{
public class GridBase
{
internal GridBase() { }
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
private void InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
public class Grid : GridItem.GridBase { }
Another option is to have GridItem explicitly implement an internal interface. This way no one outside of your assembly can use the interface by name and therefore cannot call InformAddedToGrid.
public class Grid
{
public void AddItem(GridItem item)
{
((IGridInformer)item).InformAddedToGrid();
}
}
public class GridItem : IGridInformer
{
void IGridInformer.InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
internal interface IGridInformer
{
void InformAddedToGrid();
}
I have a class in the same namespace as my form. Is it possible for me to access methods/properties of my form controls from my class? How can I accomplish this?
You need to make your controls public, however I wouldn't do that. I'd rather expose just what I need from my controls. So say if I needed access to the text in a text box:
public class Form1 : Form
{
public string TextBoxText
{
get{return this.textBox1.Text;}
set{this.textBox1.Text = value;}
}
}
One way is to pass the form into the class like so:
class MyClass
{
public void ProcessForm(Form myForm)
{
myForm.....; // You can access it here
}
}
and expose the Controls that you want so that you can access them but really you should pass only what you need to the class, instead of the whole form itself
If you pass a reference of your form to your class you should be able to access methods and properties of your form from your class:
public class MyClass
{
private Form form;
public void GiveForm(Form form)
{
this.form = form;
}
}
You need to generate stubs.
For that
In your custom class write a constructor
public YourClass(Main main)
{
// TODO: Complete member initialization
this.main = main;
}
then in main class/form class, initialize your class
YourClass yesMyClass = YourClass(this);
If your want to access form components on your custom class then,
this.main.label1.Text="I done that smartly'