How to Extend form class in C#? [duplicate] - c#

This question already has answers here:
How can I get Visual Studio 2008 Windows Forms designer to render a Form that implements an abstract base class?
(10 answers)
Closed 8 years ago.
I have designed 3 different win forms in c#.
public partial class SLOSPR : form
{
public bool IsCallable;
public void PopulateData();
}
public partial class SLOFIX : form
{
public bool IsCallable;
public void PopulateData();
}
public partial class SPDBID : form
{
public bool IsCallable;
public void PopulateData();
}
I have declared one member variable IsCallable in every form's class and a member function PopulateData() in every form's class. It is so because, in a code segment I want to declare one variable of a form type, and want to assign an object of any of the above 3 classes and use that IsCallable variable and call PopulateData().
like this:
public form RetForm()
{
form frm=new /* constructor of any 3 forms mentioned above*/
//this function can return any of the three types which will be decided at run time.
return frm;
}
form frm=RetForm();
here i want to use IsCallable and call PopulateData().
like this:
if(frm.Iscallable)
frm.PopulateData();
Which is not possible syntactically as Iscallable and PopulateData is not member of form class
To solve this problem I extended the form class to an abstract class and declared those 3 forms from the extended class.
public abstract class EXTENDED_FORM : form
{
public bool IsCallable;
public abstract void PopulateData();
}
and changed the definition of those 3 forms like this.
public partial class SLOSPR : EXTENDED_FORM
{
public override void PopulateData()
{
/*body for SLOSPR */
}
}
public partial class SLOFIX : EXTENDED_FORM
{
public override void PopulateData()
{
/*body for SLOFIX */
}
}
public partial class SPDBID : EXTENDED_FORM
{
public override void PopulateData()
{
/*body for SPDBID*/
}
}
Now I did like this:
public EXTENDED_FORM RetForm()
{
EXTENDED_FORM frm=new /* constructor of any 3 forms mentioned above*/
//this function can return any of the three types which will be decided at run time.
return frm;
}
EXTENDED_FORM frm=RetForm();
Now I can call like this:
if(frm.Iscallable)
frm.PopulateData();
Automatically overridden PopulateData will be called.
Finally I made my purpose. But as I changed
public partial class SLOSPR : form /*[Designer generated code]*/
to
public partial class SLOSPR : EXTENDED_FORM
The GUI designer in Visual Studio gets messed up, showing the following page.
How to get rid of this, also my purpose gets fulfilled without hampering the designer???

don't make EXTENDED_FORM abstract; remove abstract from its declaration and add protected constructor without parameters

Related

call the function in another class(c#)

I am trying to migrate one of my macOS app to Windows UWP.
There is a requirement that I need to call the function in another class
namespace MyApp
{
public sealed partial class MainPage : Page
{
public bool isOk;
public MainPage()
{
}
public void doSomething(){
};
/*
public static void doSomething(){
isOk=false;// isOk is inaccessible
};*/
}
public sealed partial class AnotherPage : Page
{
public AnotherPage()
{
//call doSomething() in MainPage
}
}
}
it is very easy to implement this in objective-c via protocol(interface)
but in c#, the mechanism of the interface is different from the objective-c protocol.
of course, I can use the code below
MainPage mainPage=new MainPage();
mainPage.dosomthing();
but I wonder if this is valid for Page object related to the XAML file.
or there is a common usage to call the function in another class?
Your comment welcome
NOTE: This is an answer to your question but from a design perspective this is bad.
You need a reference to the instantiated MainPage. I'm sure there's one in the framework but for example just so this can be understood let's make a public static class to hold this reference.
public static class Global
{
public static Page MainPage { get; set; }
}
Now in the MainPage constructor assign itself to this property of the static Global class.
public MainPage()
{
Global.MainPage = this;
}
Now from any other page you can access it.
public AnotherPage()
{
Global.MainPage.doSomething();
}

C# WinForms 'this.Controls.Find' in a separate class

I am trying to divide my program into classes to reduce clutter and increase readability.
In one of my methods, I need to find the location of a label on the screen.
this.Controls.Find worked before I moved everything into separate classes but it doesn't exist anymore because I am no longer executing it in the same class as the controls. I tried Main.Controls.Find (Main.cs is where my form is executed and set out) but this also didn't work and I got the error, "An object reference is required for the non-static field, method, or property 'Control.Controls'"
How do I reference the controls? Do I need to add an additional using statement?
Thanks,
Josh
You need a reference to the form, passed down to the newly introduced method (or class).
Before
public class Main : Form {
public void Whatever() {
...
this.Controls.Find(...);
}
}
After
public class Main : Form {
public void Whatever() {
...
new Helpers().HelperMethod( this );
}
}
public class Helpers {
public void HelperMethod( Form form ) {
...
form.Controls.Find
}
}
or
public class Main : Form {
public void Whatever() {
...
new Helpers( this ).HelperMethod();
}
}
public class Helpers {
private Form Form { get; set; }
public Helpers( Form form ) {
this.Form = form;
}
public void HelperMethod() {
...
this.Form.Controls.Find
}
}

C# Base Class MyFrm could not be loaded

I have the following custom Form (MyFrm) which inherits from Form.
public class MyFrm<T>: Form where T: class
{
}
And following is my Form1:
public partial class Form1: MyFrm<CONTACTS_BASE>
{
public Form1()
{
InitializeComponent();
MyInitialize();
}
public void MyInitialize()
{
}
}
as can be seen, there is nothing exceptional, However, when right click and select view designer I get the following error:
The 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 'MyGym.Controls.MyFrm' could not be loaded. Ensure the assembly has been referenced and that all projects have been built.
when I remove the part below and edit my Form1 accordingly I get no errors when I go to the designer mode.
: Form where T: class
Why am I facing this issue? is there a fix for this?
Thanks
I believe you need to explicitly provide the InitializeComponent() method so that the Visual Studio IDE (Designer) works properly.
public class MyFrm<T> : Form
where T : class
{
public MyFrm() : base()
{
InitializeComponent();
}
private void InitializeComponent()
{
}
}
and then chain the constructors it together
public partial class Form1 : MyFrm<CONTACTS_BASE>
{
public Form1() : base()
{
InitializeComponent();
MyInitialize();
}
public void MyInitialize()
{
}
}
Note that : base was added to the constructor. However, in this example it's a bit overkill as the base constructor would already be called implicitly. I provided this addition, due to this answer. It states you must keep the constructor parameter-less in your base class.

C# override base form text - InitializeComponent

Problem: When I execute my code it pulls up the code correctly from the inherited base class and changes the text of the base form correctly. But as soon as I, in debugger mode in VS2013, come back into the derived class and step over the InitizlieComponent(); call everything is reverted back. When I say 'reverted back' I mean that thing go back to the way that they were in the designer for the derived form.
All help would be appreciated!
Derived Class
public partial class appSuiteMenu : App.baseForm
{
public appSuiteMenu()
: base("App Suite")
{
InitializeComponent();
}
}
Base Class
public partial class baseForm : Form
{
public baseForm() { InitializeComponent(); } //Required or designer breaks
public baseForm(string formTitle=null)
{
this.initialize(formTitle);
}
private void initialize(string formTitle)
{
base.text = formTitle + " - " + //Other objects are called from the class
}
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
}
}
}
My guess would be the second call to the "InitializeComponent()" inside the derived class.
What is does, is exactly what you said. It overrwrites everything from the base initialization.
I believe you can remove it and it'll be fine:
public appSuiteMenu()
: base("App Suite")
{
}
Read more about it in here: http://www.dotnetperls.com/initializecomponent
Edit:
Here is some tests I did with two forms. One is derived from the other. The base form hase a label. The second from adds another label. When creating a form of the derived type, tou get a form with two labels. What I did was use InitializeComponent(); in both base and derived forms.
The code:
public partial class BaseForm : Form
{
public BaseForm()
{
InitializeComponent();
label1.Text = "asdf";
}
}
...
public partial class DerivedForm : BaseForm
{
public DerivedForm()
{
InitializeComponent();
label2.Text = "asdfasfd";
}
}
What happens in execution of the code is that the base initialization happens. Then the derived initialization adds only the add functionality.
It seems pretty straightforward, but Iv'e noticed you had only one InitializeComponent(); in the code above that will actually happen.
Dave,
Your edited posted is nearly what I ended up doing to correct my problem. Since I was overriding the .Text() property of the base form, I found that I didn't even have to pass anything in the constructor. Simply setting the form text in the code, or designer, changed everything for me.

Base Class interacting with Derived class Controls in Winforms C#

Lets Say I have a FormBase Class that is inherited from 'Form', and I have winforms Form that inherit from FormBase, how do I get access and manipulate the Controls in the Child Form as follows:
public class FormBase : Form
{
protected FormBase()
{
//for each Control in Child form Controls
//Do something with the Controls
}
}
public partial class Products : FormBase
{
public Products()
{
InitializeComponent();
}
}
You should not access the controls of the child form in the constructor of the base form. Because base constructor will be run first and child constructor after that.
Instead you should do
public class FormBase : Form
{
protected override void OnLoad(EventArgs e)
{
//access the child controls here. Take a look at Will A's answer
base.OnLoad(e);
}
}
Take a look at this question & answers - this should give you what you need, albeit with some adaptation.

Categories

Resources