C#/.NET - Better way to organize - c#

Let's say I have a System.Windows.Forms.Form named MyForm and two nested System.Windows.Forms.Panel named MyPanel and MyOtherPanel. Inside each panel, there are buttons, labels, etc. Is there a way to split MyPanel and MyOtherPanel into another class and render them in the GUI as System.Windows.Forms.Panel.
The main purpose of my question is to avoid populating the name space of MyForm.
Thanks!

To organize WinForm code better, One important design consideration you can make, that is to have each form a Handler. So your code is separate from WinForm.cs. For Example, you can have MyFormHandler.cs, Which holds/Implements your MyPanel1 and MyOtherPanel1 logic. It is a better approach to separate your code from .NET Winform code and easy to reuse, extend and maintain.

You can create a new class to inherit a panel. Then you can override whatever properties or methods you want changed from the panel. In which case when you call them from your main form or MyForm you will need to initialize them i.e.
void main(){
MyPanelClass meaningfulpanelname = new MyPanelClass();
meaningfulpanelname.Show();
}
public class CustomPanel : Panel
{
protected override void functionToOverride(EventArgs e)
{
//what you want done
}
}
I have included .Show() because I don't remember whether when creating dynamically in C# you need to do so or not.
Since it is in a Windows Form Application I am taking a guess that you do.
I could also see the syntax being
this.Controls.Add(meaningfulpanelname);
within void main() instead of
meaningfulpanelname.Show();

Related

How to update Templates?

Currently I'm creating a really big project in Visual Studio 2012, where there are some common settings for each form ("Cancel" and "Save" buttons, Methods that change in every form but have the same name, font sizes and types, form color etc.) it will save me a lot of time if I could do all the design a single windows form and when I edit or modify it, have the changes reflected in the other forms as well.
Let's say I need 10 forms, to create them I would choose this default format and have my menu and basic objects already placed and designed; then after 10 forms I decided to move a button a bit, but don't want to go to every form and move it; just change it in the original format, refresh and all my forms will have that button in the new location.
I used Templates as recommended by Can one set the default properties for new WinForms created in Visual Studio?. But I still have the issue that if I change something in the template it won't refresh in every other form created with the template to that point.
I've already thought of changing the InitializeComponent in the WinForm default format, but this is not recommended and I wouldn't want any errors from this later on.
Any ideas?
Thanks in advance
Inheritance will work for your solution.
Create "base" form with all "common" controls
Create new "derived" form and change form to inherit from your "base" form.
If you have some common logic in base form, which need to be "overridden" in derived forms - put it to the virtual method
// Base form
protected virtual void Close()
{
// Base logic
}
private void CloseButton_Click(object sender, EventArgs e)
{
Close();
}
// In derived form - just override "Close" method
protected override void Close()
{
// custom logic - will be executed when "Close" button clicked
}
In base form leave empty space for custom controls. Because you will not be able access baseform controls through designer in derived form.
Another approach - Model-View-ViewModel(MVVM)
- Introduce own UserControl with common controls(view) which have property - instance of ViewModel.(Viewmodel will contains behaviour logic and possibility to change "base" settings.)
- Add this user control to all "derived" forms and set UserControl.ViewModelProperty to instance which will represent logic for this particular form.
Without knowing "full" context of your goals - difficult to suggest more, but I am pretty sure you can build maintainable relations between forms, which can share common logic and view.
No, there is nothing you can do. Once you use a template to create a project or a file, it becomes a one-off. You have to edit it manually, or use a text editor that is powerful enough to employ a find and replace with pattern matching and capture group insertion.

WPF: use the same xaml file with different codebehinds

I'm writing a wpf program that needs several usercontrols that look exactly the same but perform different functions. With winForms, I could just extend the base control and add the functionality, but as far as I know, it's impossible to inherit xaml files. Is there any way I can have different codebehind classes that all use the same xaml file for their control?
You might be able to do this using MVVM pattern and create multiple VMs which perhaps implement the same interface. The XAML view could then be bound to any of your VMs relying on the fact they share the same interface.
In this approach you'd not use the code behind at all.
One way to do it is by using inheritance. A very simple example would be a UserControl with a single button, that should display different contents in a MessageBox.
We will have something like this:
public abstract class SomeUserControl : UserControl
{
//declared by XAML (can be made public with x:FieldModifier="public")
public Button MyButton;
//code-behind
public SomeUserControl() {
InitializeComponent();
}
}
public class MySpecialControl : SomeUserControl {
public MySpecialControl() {
MyButton.Click += (sender, e) => MessageBox.Show("Bla");
}
}
To use the MySpecialControl, just declare it in XAML like you did with your previous one:
<myNamespace:MySpecialControl />
Note that you can also create an abstract method for the button click, if the variation in behavior is not so big.
With winForms, I could just extend the base control
And one can't do similar in WPF?
Create a custom composite control with a dependency property(ies) which would set the mode of the control to fit its the target consumer's needs.
The control could be based on an existing control or controls.

Calling Methods from seperate usercontrols in the same form

I really had no idea what to title this question.
Assume I have a windows form application. The GUI is complex enough to require two custom user controls, "LeftSide" and "Rightside" which each are composed from various buttons, labels, and maybe even another custom user control.
My question:
I am in in the scope of the "Rightside" control. How would I call a method from the "Leftside" control?
I am using Visual Studio 2008.
The simplest solution is to make a property on the RightSide control of type LeftSide, then set it to the LeftSide instance in the form designer.
You can then call public methods on the property.
However, this is poor design.
Each usercontrol should be a self-contained block that doesn't need to directly interact with other usercontrols.
You should consider restructuring your form.
Exact equivalent with standard WF controls: how to keep the text of one text box in sync with another:
private void textBox1_TextChanged(object sender, EventArgs e) {
textBox2.Text = textBox1.Text;
}
Necessary ingredients: an event on your user control that is fired when something interesting happens. And public properties.

Winform inheritance and default form size

An application I'm working will have a number of forms with a lot of shared functionality. For instance, each form will have a DataGridView, many of the same buttons, much of the same UI code and so on.
I'd like to implement this by creating a base version of this common form, subclass it for all these very-similar-but-not-quite-the-same child forms, and tack on whatever additional controls and features I need for each of them.
I've already figured out that it helps to make the base form's controls protected because this allows things like anchoring to work propertly. However, I have yet to find a way to automatically make the derived forms the same size as the base form.
Experience tells me there should be a simple way to do this. While it's not much of a problem to just type in the required size by hand for every derived form right after creating it, I'd prefer to make everything as clean, simple, and automatic as possible.
I find it interesting that your derived forms do not automatically inherit the size from their base form, because this should work without you having to do anything about it.
Suspected cause of your problem:
I suspect your problem results from the fact that you're using Visual Studio's Forms Designer to edit the forms. Whenever you've edited a form, Windows Forms Designer generates the required code in the InitializeComponent method of your forms. Among all the generated code are assignments that set a form's size, even if it is identical to the base form's size. Therefore you might have to manually comment out those assignments if you want your derived form to have the same size as the base form, even when you change the base form's size after creating the derived forms. (However, I don't know if that might lead to further problems with the controls' positioning & layouting.)
// Code to be commented out in your derived form's InitializeComponent method:
this.AutoScaleDimensions = new System.Drawing.SizeF(...);
this.ClientSize = new System.Drawing.Size(...);
Once these lines are commented out, the size as set in your base form's InitializeComponent will be used for the derived form.
A workaround solution:
You can do the following so that you don't have to manually comment-out designer-generated code every time you've edited a form:
Create an form derived from your base form; let's call it FrozenBaseForm. You will derive all other forms from this class instead of directly from the base form. Now, in this "intermediate" class, you define a new property ClientSize:
public class FrozenBaseForm : BaseForm
{
new public SizeF ClientSize
{
get { return base.ClientSize; }
set { }
}
}
This will cause all assignments to ClientSize to have no effect at all and therefore preserve the size from the base form. This feels like a hack to tell the truth, but it seems to work. You might have to hide the Size property in the same way btw.
As said, derive your forms from FrozenBaseForm instead of from BaseForm directly:
public class DerivedForm1 : FrozenBaseForm { ... }
public class DerivedForm2 : FrozenBaseForm { ... }
...
Another option (last resort if all else fails):
As a last resort, you could simply forget about the Forms Designer and just define the derived forms manually in the code editor (though I personally would not want to do this):
public class DerivedForm : BaseForm
{
public DerivedForm()
{
// make all necessary changes to the base form:
...
}
}
public partial class derivedForm : baseForm
{
public derivedForm()
{
InitializeComponent();
this.Width = base.Width;
this.Height = base.Height;
}
}
Why not make the BaseForm set the size of itself?
public partial class BaseForm : Form
{
public BaseForm()
{
InitializeComponent();
// you could hardcode these or retrieve these values from a
// config file or something
this.Width = 640;
this.Height = 468;
}
}
Wouldn't this do what you want?

Winform & user control - C#

I have a Form and a UserControl. The UserControl has a menu, and the form has a tabstrip (General, Food, Vitamins etc).
In the UserControl, I have the following code: (Form name is frmForm, the tab names in the form are tabGeneral,tabFood, tabVitamins)
frmForm fm=new frmForm();
fm.tabMain.Selected=tabVitamins;
I call these line from the UserControl to capture the tab to get selected on the form, but it does not select the vitamins tab.
Where am I going wrong? I have access specifier as Protected Internal for tabs in the form.
Please advice.
Thanks,
Karthick
When you write new frmForm(), you're creating a completely new instance of frmForm, which is then discarded.
To get the frmForm instance that holds your control, call the FindForm() method and cast to frmForm.
For example:
frmForm myForm = FindForm() as frmForm;
if(myForm != null)
myForm.tabMain.SelectedTab = myForm.tabVitamins;
If the control is on some other form, this code won't do anything.
By the way, Hungarian notation is frowned upon in .Net.
Your form should probably be named something like MainForm.
SLaks has correctly pointed out your fundamental error, and given you a valid example of a way, via a call to the method 'FindForm, to get the Form the UserControl is sited on.
It may be valuable to you to keep in mind that a UserControl (and all Controls) also has a 'Parent property, but, of course, a UserControl could be placed inside another Control on a Form (like your UserControl could be inside a Panel on the Form) : in that case the UserControl's Parent would be the control it's inside on the Form (like, a Panel), not the Form itself, but 'FindForm will do the right thing to get you the Form it's on.
However you are calling a Method every time you use 'FindForm, and "best practice" suggests that what you want to do is to "inject" a reference to the Form into the UserControl at run-time so that it can always access its Form property easily, without calling a 'Method.
In your example, on a practical level, this (calling the Method) may make almost no difference in performance, but, imho, as you get to a place with WinForms and .NET where you might have a UserControl that will need access to its Parent Form very frequently, this will pay off, and it's a better way to structure your code in the long run, for maintenance.
Wes showed you one way you can "embed" (inject) the UserControl's hosting Form : using an overloaded constructor for the UserControl. But that requires you to modify the Designer.cs file in standard WinForms, and I strongly advise you against that, even though it will work. Particularly if you are just "getting your feet on the ground" in .NET, I strongly advise you against modifying it, or anything having to do with the Form's constructor and its internal call to : InitializeComponent();
Also, as you progress with WinForms you are going to meet many situations where you are going to want instances of "objects" (a Control, a Form, an instance of a Class) to contain references to other instances of "objects.
If you can understand and use one simple use of "injection" here, you are going to make progress to make yourself ready to handle more complex .Net programming in the future.
Another way is to put a Public Property in the UserControl that can be set in code from the MainForm. In the UserControl something like :
private frmForm ParentForm;
public frmForm UCParentForm
{
set { ParentForm = value; }
}
So then in your main form's code, perhaps in the Load event like this :
private void frmForm_Load(object sender, EventArgs e)
{
TheUserControl.UCParentForm = this;
}
or when you need to, you set the UserControl's 'ParentForm property once. So you have eliminated using the method 'FindForm().
In this case, if you only want access to a specific control on the UserControl's Parent Form, like a TabControl, you might consider that you want to make the Property you set of type TabControl, rather than Form : the same coding technique shown above can be used in the UserControl :
private TabControl mainFormTabControl;
public TabControl MainFormTabControl
{
set { mainFormTabControl = value; }
}
imho, it is when you are creating UserControls dynamically at run-time, using an overloaded constructor, as Wes suggests, is the best strategy. And using overloaded constructors has many, many others uses in .NET that you'll get into.
good luck !
You should not be creating a new frmForm() inside the user control. You could pass a reference to the frmForm to the user control.
In your user control constructor try something like this.
private frmForm fm;
public YourUserControl(frmForm fm)
{
this.fm = fm;
}
Then you could use.
fm.tabMain.Selected=tabVitamins;
Does that help?

Categories

Resources