How manage a large interface for a WinForms application? - c#

When thinking of the SRP, I find that an application that I'm writing is getting out of hand for our main interface/form. I'd like to change it before we get too far into the project.
What are some techniques for making a large interface that has a "drawing surface" with toolbars, menus etc? I'd also like it to be easy for this form to be testable. Should there be other classes that know how to control the MainForm such as a ChangedStateTracker (to monitor dirty state), DocumentCreator or something along those lines to "File > New" a new document?
The problem that I'm running into is there are so many methods inside the MainForm.cs and it's really starting to get ugly to maintain.
This can be marked CW if necessary. Any other hints/tips would be greatly appreciated.

If this is an option, I would create a set of user controls that together produce the entire form.
These separate user controls can then have their own responsibility and can be tested separately.
For the logic itself, create classes.
You can create classes like CreateDocumentCommand that implement some functionality. When e.g. the new document button/menu item is clicked, create an instance of this class and execute it.
public interface ICommand
{
bool CanExecute { get; }
void Execute();
}
public class SaveDocumentCommand : ICommand
{
public bool CanExecute
{
get
{
return MainForm.Instance.CurrentDocument.IsDirty;
}
}
public void Execute()
{
// Save your document here.
}
}
This by the way is how WPF does it.

Jeremy Miller has written about this a few times - these should get you started:
http://codebetter.com/blogs/jeremy.miller/articles/129546.aspx
http://www.jeremydmiller.com/ppatterns/default.aspx

Related

Method of displaying message dialogs

I have a collection of programs that repeatedly display messages to the user for various reasons. My initial thought for this, was a basic static helper method(s):
public class Message
{
public static void ShowMessage(...)
{
...
The method itself does various things (i.e. it isn't just a wrapper for MessageBox.Show()).
Obviously, this creates a problem for testing. So the next solution that springs to mind is using a singleton pattern.
I'm sure the neatest way is dependency injection, but that presents the problem of having to instantiate a new stateless object each time I want to display a message.
So my target is to create a structure that allows a single call to a common class.
Message.ShowMessage("hello");
Is there a way to achieve this simply while maintaining testability?
My approach would be using strategy pattern (which might be a bit of an overkill depending on the size of the project).
interface IMessageShowingStrategy
{
void ShowMessage(...)
}
class RealMessageShowingStrategy : IMessageShowingStrategy
{
void ShowMessage(...)
{
// Real code
}
}
class TestingMessageShowingStrategy : IMessageShowingStrategy
{
void ShowMessage(...)
{
// Code used for testing
}
}
class Message
{
IMessageShowingStrategy messageStrategy;
void ShowMessage(...)
{
this.messageStrategy.ShowMessage(...);
}
}
Then you can choose which strategy to use. For testing, you can use an instance of TestingMessageShowingStrategy (maybe when the application is started with a -debug switch or something) and otherwise use the Real strategy. This is what I've been using for Unit tests.
you can achieve this by simply extending the form class and creating methods as you required.

Dynamically creating WPF controls from XML and stacking them

I want to run through a series of steps that comprise a complete test. Some of these steps are automatic (so informational) and others require user interaction. Test steps are not known at compile time, they are using MEF to be loaded.
Currently I have something like
public abstract class TestRunnerBase
{
public abstract void Run();
}
With a list of steps like this:
List<TestRunnerBase> Steps = new List<TestRunnerBase>();
So all data representing a test serializable and that works okay so far. However what I really need is for a user to load a test from XML, it then walks them through the options displaying information on screen and gathering results.
But trying to work out how to create a control for data that is unknown at compile time has ended up with me getting a bit stuck on the best approach.
I am thinking to do this I would have a list of custom controls (1 a step) and the GUI would display the first step, wait for that control to be complete (I was thinking here that a raised event might work?) and then display the next if available and so on until the test is complete.
So is it possible to do this in WPF? Can you create a stack of controls in WPF that can each raise the same event to the parent container or is there a better way to do it?
But if I also use the abstract class I can't then derive a control from it also as no multiple inheritance in C# of course.
I would use MVVM and create a viewmodel that understood how to navigate the list of steps, providing a wizard type structure (prev/next) and exposing the current step.
I assume that while you have different kinds of potentially unknown steps that you have a concrete set of input options (bool, text, date, int, etc) then you could use a abstract property on your TestRunnerBase that identifies what kind of input is required (or none) using an enum that must be overriden.
Then you could use datatemplates and/or data triggers to control what is shown for each step of the test. The main viewmodel could check that conditions are right for going to the next step (perhaps a validate on your test).
Some psuedo code to get you thinking:
public enum TestInput
{
None,
Bool,
Text
}
public abstract class TestRunnerBase
{
public abstract TestInput TestInput { get; }
public bool BoolInput { get; set; }
public string TextInput { get; set; }
public abstract bool CanRun()
public abstract void Run();
}
public class MainViewModel
{
List<TestRunnerBase> Steps = new List<TestRunnerBase>();
public TestRunnerBase CurrentStep {get;set;};
public MainViewModel()
{
//loads the Steps
CurrentStep = Steps
}
public Command RunStepCommand
{
if (CurrentStep.CanRun())
{
CurrentStep.Run();
CurrentStep = Steps.Next(); //you get the idea
}
}
}
For your XAML you would bind a ContentPresenter to CurrentStep and use a datatemplate (and maybe data triggers) to control what is visible to the user (and of course bound to the UI).
In WPF you can dynamically create controls using XAML. Simply create a XAML snippet with the layout you want (either programatically or by hand) and use XamlReader.Parse to create the entire tree from the snippet. The returned object can then be inserted somewhere in the visual tree of your window.
To generate events from the visual tree generated by XamlReader you can use routed events.

C# Proper Program Structure

So I had a simple program that was roughly click a button and it preformed a task, nothing fancy, very simple. Now, I have added a LOT more features task for it to do. It does about 5 different main more complex tasks. The task have little input in the sense of like the common class/namespace examples dealing with insert name, address, phone number, etc. The task is more like set up the settings(check/uncheck the checkboxes) on how you want to preform the task and then click the button to preform it. The code has grown out of control. So I am now trying to organize it. I am self taught, so I am running into some trouble, but this is what I am thinking so far for organization. Any comments about the proper way to organize this would be appreciated.
namespace namespaceName
class task1Name
methods for task1
class task1Name
methods for task2
class task2Name
methods for task3
class task3Name
methods for task4
class task5Name
methods for task5
Now I also have a windows form for the program and another windows form for the pop up settings window. The big question is where do these fit in exactly? public partial class className : Form? Will this setup allow the methods in the different task classes to still interact with the form webbrowser control? The form has a couple of webbrowser controls and the task are prformed in the webbrowser control.
I guess in general I am just trying to find the best way to manage the code and to properly setup/structure the code. From reading this How to use separate .cs files in C#? maybe I just stick with the one class/file, since the task involve the webbrowser in windows form.
Ive been looking at http://msdn.microsoft.com/en-us/library/w2a9a9s3%28v=vs.100%29.aspx and the related sections listed below the code example
Breaking out your program into more maintainable chunks - the art of refactoring - can be a very challenging, but also a very rewarding, part of programming. Like #Keith said, you'll learn by doing.
The most important advice is to refactor in small, self-contained steps.
There are a number of ways that you could start this. If you want detailed advice, it would help to know what some of the code looks like. For example, what are the "task" methods' signatures (their names, arguments, and return type) and how do they interact with the "settings".
Here's one suggestion I would make. The single-responsibility principle suggests that the separate tasks should be in separate classes (and, usually, that means they should be in separate files - but that doesn't matter to the compiler at all, it's just for readability). If the tasks are in separate classes, they'll need a way to know what the settings on the form are. But the tasks don't care about the fact that the settings are on a form - they just want the values of the settings. So, create a data structure that contains all the settings from the form. Then, write a single method in the form class that reads all the settings from the controls, so you have that all in one place. Then, in your button click handler for each task's button, just call that method to get the settings, and pass the settings to the particular task that you're trying to run. Presto!
Your code would then look something like this: EDIT: I forgot that the WebBrowser control needs to be passed to the tasks. Fixed.
// Note: All classes and structs go in the same namespace, but each goes in its own .cs file.
// Use a struct, rather than a class, when you just need a small set of values to pass around
struct MySettings
{
public int NumberOfWidgets { get; set; }
public string GadgetFilename { get; set; }
public bool LaunchRocket { get; set; }
}
partial class MyForm
{
// ...constructor, etc.
private void ButtonForTask1_Clicked(object sender, EventArgs e)
{
var settings = ReadSettingsFromControls();
var task1 = new Task1(settings);
task1.DoTheTask(ref this.WebBrowserControl1);
}
private void ButtonForTask2_Clicked(object sender, EventArgs e)
{
var settings = ReadSettingsFromControls();
var task2 = new Task2(settings);
task2.DoTheTask(ref this.WebBrowserControl1);
}
// ... and so on for the other tasks
private MySettings ReadSettingsFromControls()
{
return new MySettings
{
NumberOfWidgets = int.Parse(this.txt_NumWidgetsTextBox.Text),
GadgetFilename = this.txt_GadgetFilenameTextBox.Text,
LaunchRocket = this.chk_LaunchPermission.Checked
};
}
}
class Task1
{
// Readonly so it can only be set in the constructor.
// (You generally don't want settings changing while you're running. :))
private readonly MySettings _settings;
public Task1(MySettings settings)
{
_settings = settings;
}
public void DoTheTask(ref WebBrowser browserControl)
{
// TODO: Do something with _settings.NumberOfWidgets and browserControl
// You can use private helper methods in this class to break out the work better
}
}
class Task2 { /* Like Task1... */ }
Hope that helps! Again, if you post some example code, you'll probably get much better advice on how to refactor it.

Design Question - OO food application

Say I have a number of usercontrols, each usercontrol inside a tabitem, inside a window.
For example, let say this is a food collection application. Then we have tabs Fruit, Vegetables and Snacks. Each tab will show a list of food of that subject, and allow the user to add, delete, modify the food in each section. The food is stored in seperate textfiles, i.e. Fruit.txt, Vegetable.txt, Snack.txt
The actual text files might look something like this (vegetable.txt):
Name Carbs Fat
Eggplant 2 1.1
Cucumber 3 0.5
etc
Now this is a large list and there is a load method which pulls all the vegetables out into a List
The question I have is this loadVegetables method is in the code behind file, and I end up repeating this load method all over the place, because I have another of other screens like ReviewAllFood, AddVegetable, etc. along with all the other load methods for fruit and snacks.
This is more of a design question, I'm wondering how I set this up to not repeat this code. I could have a VegetableManager (or something) class where the load method is, but does this actually mean less repeated code? Then in each screen I have to create object of VegetableManager and call its load method anyway. So I guess efficiency wise its no better, but I do achieve a better design.
I think I'm missing something here. It's been a while since I studied cohesion and coupling and I think i'm confusing myself with these concepts at the moment. Appreciate if someone could suggest a design for this situation and explain why they chose it and why its better than how i'm doing it at the moment.
Thanks for reading.
I could have a VegetableManager (or
something) class where the load method
is, but does this actually mean less
repeated code? Then in each screen I
have to create object of
VegetableManager and call its load
method anyway.
The point of doing this is not efficiency (i.e. performance). The point is to encapsulate the details of loading that data into a single isolated object. Say for example that your site gets really big and you decide to move the data storage to a database for scalability and performance. In the existing code as you described, you'll have to go through each user control or page and change the logic of the load method. At the best this is a pain, and at the worst you miss some or copy-paste incorrectly. If the logic is encapsulated into a dedicated object, whose only responsibility is to know how to load the data from somewhere, then you only have to make the change once.
codebehind of user control:
protected void Page_Load(object sender, EventArgs e) {
var veggieManager = new VegetableManager();
VeggieListControl.DataSource = veggieManager.GetAll();
VeggieListControl.DataBind();
}
VegetableManager.cs:
public class VegetableManager {
private static Collection<Vegetable> _veggies;
private static object _veggieLock;
public ReadOnlyCollection<Vegetable> GetAll() {
if (_veggies == null) {
lock(_veggieLock) { //synchronize access to shared data
if (_veggies == null) { // double-checked lock
// logic to load the data into _veggies
}
}
}
return new ReadOnlyCollection(_veggies);
}
public void Add(Vegetable veggie) {
GetAll(); // call this to ensure that the data is loaded into _veggies
lock(_veggieLock) { //synchronize access to shared data
_veggies.Add(veggie);
// logic to write out the updated list of _veggies to the file
}
}
}
Because _veggies is static, there is only one collection of veggies in memory, despite the fact that multiple callers will instantiate VegetableManager. But because it's static, if you have a multi-threaded application (e.g. a website) you must synchronize access to that field across all threads (hence the locks).
This is the tip of the iceberg in terms of good object-orientation. I recommend perusing UncleBob's SOLID principles, and Domain-Driven Design (free e-book).
So, yes you are repeating something, but all you're repeating is a method call, and that is ok to repeat. DRY means to mitigate the duplication of "logical" code, i.e. decision-making and algorithms; simple method calls do not fall under this. However, if you want, you can consolidate logic into a base class do this, effectively isolating the user controls from having to know about VegetableManager, though I think this is object-orientation overkill, or OOO :-)
public abstract class FoodUserControl : UserControl {
protected List<Vegetable> GetVeggies() {
return new VegetableManager().GetAll();
}
}
Then your actual controls would derive from this instead of from UserControl.
Update
Eager-loading VegetableManager.cs:
public class VegetableManager {
private static Collection<Vegetable> _veggies;
private static object _veggieLock;
static VegetableManager() {
// logic to load veggies from file
}
public ReadOnlyCollection<Vegetable> GetAll() {
return new ReadOnlyCollection(_veggies);
}
public void Add(Vegetable veggie) {
lock(_veggieLock) { //synchronize access to shared data
_veggies.Add(veggie);
// logic to write out the updated list of _veggies to the file
}
}
}
Notice this eager-loading version doesn't have to do double-checked locking around the load code in the constructor. Also notice that the load code is in a static constructor, since this code initializes a static field (otherwise, you'd be reloading the data from the file on every construction into the same shared static field). Because veggies are eager-loaded, you don't need to load in GetAll or Add.
I would suggest pulling the vegetables (or whatever it is you're loading) out once when you read the file. Then you store them in some underlying data model. You can bind the list, and whatever other controls you need to, to the underlying data model. The data gets loaded once, but various views can display it.
EDIT: Adding code
List<T> loadObjects(File file, ILineConversionStrategy strategy) {
// read eaqch line of the file
// for each line
T object = strategy.readLine(line);
list.add(object);
return listOfObjects;
}
EDIT 2: Data model
class FoodModel {
List<Vegetable> getVegetables();
List<Fruit> getFruit();
// etc
}
I would use the repository pattern for this. As a start, create one class containing methods to retrieve the objects from each text file:
public class FoodRepository
{
public IList<Vegetable> GetVegetables() { ... }
public IList<Fruit> GetFruit() { ... }
// etc.
}
This class should be the only class in your application that is aware that foods are actually stored in text files.
Once you get that working you might want to consider caching frequently used data to improve performance.
public interface IEatable {}
class Vegitable : IEatable
{ string Name { get; set; } }
class Fruit : IEatable
{ string Name { get; set; } }
public interface IEatableManager
{
List<Vegitables> LoadEatables(string filePath);
}
public class VetabaleManager : IEatableManager
{
#region IEatableManagerMembers
public List<Vegitable> LoadVegs(string filePath)
{
throw new NotImplementedException();
}
#endregion
}
.
.
.
There are several things you need to consider for using a design like above
Dependency Injection pattern
Continuous Integration
DRY
and a must read:
How can I practice better
object-oriented programming?

Best way to access a control on another form in Windows Forms?

First off, this is a question about a desktop application using Windows Forms, not an ASP.NET question.
I need to interact with controls on other forms. I am trying to access the controls by using, for example, the following...
otherForm.Controls["nameOfControl"].Visible = false;
It doesn't work the way I would expect. I end up with an exception thrown from Main. However, if I make the controls public instead of private, I can then access them directly, as so...
otherForm.nameOfControl.Visible = false;
But is that the best way to do it? Is making the controls public on the other form considered "best practice"? Is there a "better" way to access controls on another form?
Further Explanation:
This is actually a sort of follow-up to another question I asked, Best method for creating a “tree-view preferences dialog” type of interface in C#?. The answer I got was great and solved many, many organizational problems I was having in terms of keeping the UI straight and easy to work with both in run-time and design-time. However, it did bring up this one niggling issue of easily controlling other aspects of the interface.
Basically, I have a root form that instantiates a lot of other forms that sit in a panel on the root form. So, for instance, a radio button on one of those sub-forms might need to alter the state of a status strip icon on the main, root form. In that case, I need the sub-form to talk to the control in the status strip of the parent (root) form. (I hope that makes sense, not in a "who's on first" kind of way.)
Instead of making the control public, you can create a property that controls its visibility:
public bool ControlIsVisible
{
get { return control.Visible; }
set { control.Visible = value; }
}
This creates a proper accessor to that control that won't expose the control's whole set of properties.
I personally would recommend NOT doing it... If it's responding to some sort of action and it needs to change its appearance, I would prefer raising an event and letting it sort itself out...
This kind of coupling between forms always makes me nervous. I always try to keep the UI as light and independent as possible..
I hope this helps. Perhaps you could expand on the scenario if not?
The first is not working of course. The controls on a form are private, visible only for that form by design.
To make it all public is also not the best way.
If I would like to expose something to the outer world (which also can mean an another form), I make a public property for it.
public Boolean nameOfControlVisible
{
get { return this.nameOfControl.Visible; }
set { this.nameOfControl.Visible = value; }
}
You can use this public property to hide or show the control or to ask the control current visibility property:
otherForm.nameOfControlVisible = true;
You can also expose full controls, but I think it is too much, you should make visible only the properties you really want to use from outside the current form.
public ControlType nameOfControlP
{
get { return this.nameOfControl; }
set { this.nameOfControl = value; }
}
After reading the additional details, I agree with robcthegeek: raise an event. Create a custom EventArgs and pass the neccessary parameters through it.
Suppose you have two forms, and you want to hide the property of one form via another:
form1 ob = new form1();
ob.Show(this);
this.Enabled= false;
and when you want to get focus back of form1 via form2 button then:
Form1 ob = new Form1();
ob.Visible = true;
this.Close();
I would handle this in the parent form. You can notify the other form that it needs to modify itself through an event.
Use an event handler to notify other the form to handle it.
Create a public property on the child form and access it from parent form (with a valid cast).
Create another constructor on the child form for setting form's initialization parameters
Create custom events and/or use (static) classes.
The best practice would be #4 if you are using non-modal forms.
You can
Create a public method with needed parameter on child form and call it from parent form (with valid cast)
Create a public property on child form and access it from parent form (with valid cast)
Create another constructor on child form for setting form's initialization parameters
Create custom events and/or use (static) classes
Best practice would be #4 if you are using non-modal forms.
With the property (highlighted) I can get the instance of the MainForm class. But this is a good practice? What do you recommend?
For this I use the property MainFormInstance that runs on the OnLoad method.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LightInfocon.Data.LightBaseProvider;
using System.Configuration;
namespace SINJRectifier
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
UserInterface userInterfaceObj = new UserInterface();
this.chklbBasesList.Items.AddRange(userInterfaceObj.ExtentsList(this.chklbBasesList));
MainFormInstance.MainFormInstanceSet = this; //Here I get the instance
}
private void btnBegin_Click(object sender, EventArgs e)
{
Maestro.ConductSymphony();
ErrorHandling.SetExcecutionIsAllow();
}
}
static class MainFormInstance //Here I get the instance
{
private static MainForm mainFormInstance;
public static MainForm MainFormInstanceSet { set { mainFormInstance = value; } }
public static MainForm MainFormInstanceGet { get { return mainFormInstance; } }
}
}
I agree with using events for this. Since I suspect that you're building an MDI-application (since you create many child forms) and creates windows dynamically and might not know when to unsubscribe from events, I would recommend that you take a look at Weak Event Patterns. Alas, this is only available for framework 3.0 and 3.5 but something similar can be implemented fairly easy with weak references.
However, if you want to find a control in a form based on the form's reference, it's not enough to simply look at the form's control collection. Since every control have it's own control collection, you will have to recurse through them all to find a specific control. You can do this with these two methods (which can be improved).
public static Control FindControl(Form form, string name)
{
foreach (Control control in form.Controls)
{
Control result = FindControl(form, control, name);
if (result != null)
return result;
}
return null;
}
private static Control FindControl(Form form, Control control, string name)
{
if (control.Name == name) {
return control;
}
foreach (Control subControl in control.Controls)
{
Control result = FindControl(form, subControl, name);
if (result != null)
return result;
}
return null;
}
#Lars, good call on the passing around of Form references, seen it as well myself. Nasty. Never seen them passed them down to the BLL layer though! That doesn't even make sense! That could have seriously impacted performance right? If somewhere in the BLL the reference was kept, the form would stay in memory right?
You have my sympathy! ;)
#Ed, RE your comment about making the Forms UserControls. Dylan has already pointed out that the root form instantiates many child forms, giving the impression of an MDI application (where I am assuming users may want to close various Forms). If I am correct in this assumption, I would think they would be best kept as forms. Certainly open to correction though :)
Do your child forms really need to be Forms? Could they be user controls instead? This way, they could easily raise events for the main form to handle and you could better encapsulate their logic into a single class (at least, logically, they are after all classes already).
#Lars: You are right here. This was something I did in my very beginning days and have not had to do it since, that is why I first suggested raising an event, but my other method would really break any semblance of encapsulation.
#Rob: Yup, sounds about right :). 0/2 on this one...
You should only ever access one view's contents from another if you're creating more complex controls/modules/components. Otherwise, you should do this through the standard Model-View-Controller architecture: You should connect the enabled state of the controls you care about to some model-level predicate that supplies the right information.
For example, if I wanted to enable a Save button only when all required information was entered, I'd have a predicate method that tells when the model objects representing that form are in a state that can be saved. Then in the context where I'm choosing whether to enable the button, I'd just use the result of that method.
This results in a much cleaner separation of business logic from presentation logic, allowing both of them to evolve more independently — letting you create one front-end with multiple back-ends, or multiple front-ends with a single back-end with ease.
It will also be much, much easier to write unit and acceptance tests for, because you can follow a "Trust But Verify" pattern in doing so:
You can write one set of tests that set up your model objects in various ways and check that the "is savable" predicate returns an appropriate result.
You can write a separate set of that check whether your Save button is connected in an appropriate fashion to the "is savable" predicate (whatever that is for your framework, in Cocoa on Mac OS X this would often be through a binding).
As long as both sets of tests are passing, you can be confident that your user interface will work the way you want it to.
This looks like a prime candidate for separating the presentation from the data model. In this case, your preferences should be stored in a separate class that fires event updates whenever a particular property changes (look into INotifyPropertyChanged if your properties are a discrete set, or into a single event if they are more free-form text-based keys).
In your tree view, you'll make the changes to your preferences model, it will then fire an event. In your other forms, you'll subscribe to the changes that you're interested in. In the event handler you use to subscribe to the property changes, you use this.InvokeRequired to see if you are on the right thread to make the UI call, if not, then use this.BeginInvoke to call the desired method to update the form.
Step 1:
string regno, exm, brd, cleg, strm, mrks, inyear;
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
string url;
regno = GridView1.Rows[e.NewEditIndex].Cells[1].Text;
exm = GridView1.Rows[e.NewEditIndex].Cells[2].Text;
brd = GridView1.Rows[e.NewEditIndex].Cells[3].Text;
cleg = GridView1.Rows[e.NewEditIndex].Cells[4].Text;
strm = GridView1.Rows[e.NewEditIndex].Cells[5].Text;
mrks = GridView1.Rows[e.NewEditIndex].Cells[6].Text;
inyear = GridView1.Rows[e.NewEditIndex].Cells[7].Text;
url = "academicinfo.aspx?regno=" + regno + ", " + exm + ", " + brd + ", " +
cleg + ", " + strm + ", " + mrks + ", " + inyear;
Response.Redirect(url);
}
Step 2:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string prm_string = Convert.ToString(Request.QueryString["regno"]);
if (prm_string != null)
{
string[] words = prm_string.Split(',');
txt_regno.Text = words[0];
txt_board.Text = words[2];
txt_college.Text = words[3];
}
}
}
public void Enable_Usercontrol1()
{
UserControl1 usercontrol1 = new UserControl1();
usercontrol1.Enabled = true;
}
/*
Put this Anywhere in your Form and Call it by Enable_Usercontrol1();
Also, Make sure the Usercontrol1 Modifiers is Set to Protected Internal
*/
Change modifier from public to internal. .Net deliberately uses private modifier instead of the public, due to preventing any illegal access to your methods/properties/controls out of your project. In fact, public modifier can accessible wherever, so They are really dangerous. Any body out of your project can access to your methods/properties. But In internal modifier no body (other of your current project) can access to your methods/properties.
Suppose you are creating a project, which has some secret fields. So If these fields being accessible out of your project, it can be dangerous, and against to your initial ideas. As one good recommendation, I can say always use internal modifier instead of public modifier.
But some strange!
I must tell also in VB.Net while our methods/properties are still private, it can be accessible from other forms/class by calling form as a variable with no any problem else.
I don't know why in this programming language behavior is different from C#. As we know both are using same Platform and they claim they are almost same Back end Platform, but as you see, they still behave differently.
But I've solved this problem with two approaches. Either; by using Interface (Which is not a recommend, as you know, Interfaces usually need public modifier, and using a public modifier is not recommend (As I told you above)),
Or
Declare your whole Form in somewhere static class and static variable and there is still internal modifier. Then when you suppose to use that form for showing to users, so pass new Form() construction to that static class/variable. Now It can be Accessible every where as you wish. But you still need some thing more.
You declare your element internal modifier too in Designer File of Form. While your Form is open, it can be accessible everywhere. It can work for you very well.
Consider This Example.
Suppose you want to access to a Form's TextBox.
So the first job is declaration of a static variable in a static class (The reason of static is ease of access without any using new keywork at future).
Second go to designer class of that Form which supposes to be accessed by other Forms. Change its TextBox modifier declaration from private to internal. Don't worry; .Net never change it again to private modifier after your changing.
Third when you want to call that form to open, so pass the new Form Construction to that static variable-->>static class.
Fourth; from any other Forms (wherever in your project) you can access to that form/control while From is open.
Look at code below (We have three object.
1- a static class (in our example we name it A)
2 - Any Form else which wants to open the final Form (has TextBox, in our example FormB).
3 - The real Form which we need to be opened, and we suppose to access to its internal TextBox1 (in our example FormC).
Look at codes below:
internal static class A
{
internal static FormC FrmC;
}
FormB ...
{
'(...)
A.FrmC = new FormC();
'(...)
}
FormC (Designer File) . . .
{
internal System.Windows.Forms.TextBox TextBox1;
}
You can access to that static Variable (here FormC) and its internal control (here Textbox1) wherever and whenever as you wish, while FormC is open.
Any Comment/idea let me know. I glad to hear from you or any body else about this topic more. Honestly I have had some problems regard to this mentioned problem in past. The best way was the second solution that I hope it can work for you. Let me know any new idea/suggestion.

Categories