I am designing a base class for TextForms and derived classes for Labels , Fields, Dialogboxes... etc.
i am using the below code
public class TextForm
{
public void Refresh()
{
}
}
public class Label : TextForms
{
public void Refresh()
{
}
}
and in my program i am instanciating many Labels .. and somewhere i need to call TextForms.Refresh() which must execute all derived classes instances Refresh() method .
i can't imagine how to do?
You can't find all the instances by default. Though, there are a few design patterns that will make it easier for you to do so. There is the Composite Design Pattern Which gives you the ability to add sub components to your components. For example, a Form/Window component will be a container of sub components like Labels and TextFields for example. Then, when you will call Refresh on the container (Form/Window - for example) it can call the Refresh on all of it's sub components.
There is also the Observable Design Pattern which let components register for 'events' (not necessarily implemented via .Net's Events). Then when you call the Refresh method on the observer, it will call the Refresh methods of all the observable's that are registered.
In your question, you write TextForms so I am assuming that this is an object that is an enumerable of some sort.
Liskows substitution principle dictates that if you have a base class of any kind you can always substitute derived classes for the base class
var textForms = new List<TextForm>();
textForms.Add(new Label());
textForms.Add(new TextBox());
so now you can simply iterate through this list as such:
foreach(var textForm in textForms){
((TextForm) textForm).Refresh();
}
You may have to tweak the example a little to get it working, but that is the general answer to your question.
Like m102 said it is unpractical if not impossible to find all instances. However, assuming you use a canvas or page to display your labels on, it is possible to get all the labels in that canvas.
TextForm tf = new TextForm();
foreach (Control ctrl in yourCanvas.Children.OfType<Label>())
{
tf.Refresh();
}
This will retrieve all the controls of type label from the canvas. This will not refresh them all at once.
Note: I do not recommend changing labels that are not visible/onscreen. It would require them to be kept in memory and this is performancewise not advised. Oh and your refresh function has a capital R (This is usually reserved for classes).
Related
I have several Control such as ToolStripMenuItem and Button that need to have a function bound to their click event. They will either generate a new Form or add a TabPage to a current TabControl. I may end up having several different Control that will need the same function, so I thought of making a Global function repository.
I would have a class named Services looking like this:
public class Services {
TabControl container;
delegate void fonction(int id);
Dictionary<string, fonction> functions = new Dictionary<string, fonction>();
public Services(TabControl control) {
container = control;
InitFunctions();
}
public Delegate Getfunction(string name) {
if (functions.ContainsKey(name))
return functions[name];
else
throw new NotImplementedException("Failed to instantiate " + name );
}
// List of all the desired functions
// Function example
private void ProductLoan(int id) {
string name = "Loan"+id.ToString();
Form newForm = new Loan();
newForm.Text = Properties.Resources.MakeLoan;
newForm.ShowDialog();
}
private void InitFunctions() {
fonction f = new fonction(ProductLoan);
functions.Add("Loan", f);
// For each functions
// f = new fonction(name);
// functions.Add(name, f);
}
}
This class would be instantiated when the program start and stored globally so it can be accessed everywhere. Correct me if I am wrong to proceed like this, but I didn't make the Services class static since it needs to have an instance of the TabControl and to initialise the function list.
I have no clue if this is a good idea so I would appreciate some advice.
What programming environment are you using? I know that in Visual Studio, if you have several controls using the same method you can make the method under one of the click events and then, for each control that requires the same method, you can bind that method by having the controls actually bind to the click event of the first control you added that method to. As far as creating a repository that contains each function necessary, I have always had better luck just making the individual click events, I would suggest just making a class to hold the functions and making it static. Because Services needs something else instantiated first, just instantiate the TabControl then the static class holding your methods.
You could create something like TabController and PopupController with public instance methods for creating tabs and forms respectively. The TabController will probably have a dependency on TabControl and the PopupContorller will have a dependency on parent form (if needed). Every Control will have it's own event handler where the method from TabController and PopupController will be called.
UPD:
Since the Controls are created dynamically, a common facility for wiring the event handlers may be a good idea. But the wiring logic should be separated from event handler implementation logic to make it more readable and maintainable. For example IntelligentEventHandlerWiringManager could have a dependencies for TabController and PopupController.
I'm creating a set of classes called *Activity which all inherit from the interface IActivity e.g.
public interface IActivity
{
void StartActivity();
}
public class MyFirstActivity : IActivity
{
public int SomeVariable {get; set;}
public MyFirstActivity(int someVariable)
{
SomeVariable = someVariable
}
public void StartActivity()
{
//some code to do stuff with SomeVariable
}
}
This is so I can create an list/array of IActivitys and run their StartActivity() methods.
Now what I want to do is to have a UserControl (for editing any variables graphically and ordering activites graphically) for each class which inherits from IActivity.
What is the best way to do this?
My thoughts are either:
Create a separate UserControl for each Activity and then create an instance of the activity in the UserControl's constructor... or...
Make each activity a UserControl which inherits from IActivity. The issue is with this is that I may want to not use the UserControl elements in other parts of the program, just using the actions that each performs and using a UserControl for this will surely use more resources when it's not needed...
Any thoughts?
Edit:
The idea is that each Activity has some properties which can be edited and each performs a distinct action which is performed when it's StartActivity is called.
Activities can either be performed in code via creating instances of activities and adding to a list. Loop through the list to perform each StartActivity in order.
Alternatively on a Form, UserControls of each activity can created and dragged round the form into the desired order by the user (which behind the scenes populates the list) and then clicks a Start button (which loops round the list calling each StartActivity in turn.
This would be using WinForms.
You should go with your 1st thought. Take the *Activity as a Property(read-only) of the specific *UserContorl, and instantiate it through the UC constructor. Then You can set the Properties of the Activity visually through the UC.
I have following class implementation (not complete, just to give an idea)
public class MySwitch{
Command command = Command.Red;
public Command GetNext() {
command = GetNext(command); // circular enum values
return command;
}
}
public enum Command { Red =0, Blue=1, Green=2}
public class LED {
public void Glow(Command command){
this.setColor(ColorForm(command));
this.Glow();
}
}
public class Commander {
public Commander(LED target, MySwitch source){
this.LED = LED;
this.MySwitch = MySwitch;
}
public void Execute(){
this.LED.Glow(this.MySwitch.GetNext());
}
}
I want these objects to map to UI items. Consider, I have win form app where switch and LED are two panel where I want GDI to draw it.
Issue is what is best way sync objects with UI elements. Options are:
Create UI element inherited with panel and should contains one
instance of object.
Create UI element (say LEDUI) inherited from BO, and should
contain container (panel) to draw and implement draw method using this.Color
(LED for example) - this will lead to file cound 2* BO
Keep UI element and BO separate and let presenter to be bridge
between them.
Implement method on BO itself to render (assuming single UI) on winform. Since
it cannot be added to winform directly, so create a CustomForm
object which allows such elements (assume IMyObj) to be added, and
call CustomFOrm.Render(), which eventually call render method of
all childElements. Pretty same way Form and controls are rendered.
Any other way
In my opinion, point 2 is better way. Please suggest what pros and cons on different way of mapping BO with UI, and how to sync them. Game developers may have better understanding.
EDIT
My mistake, there could be many LED and switches. Each switch may be attached to many LED. Also the classes I have created is independent of UI. I don't expect solution to how to find the control and glow, but what is the best way to implement if you are given these classes and told to make a winform app, assuming u will least touch the classes as well as write minimum code, along with following standard way of UI development
I've always been taught that referencing goes before inheriting, that if you don't have to access protected members of a certain class you better create an object of that type in your class than inherit the whole class (correct me please if im wrong).
in that light option 3 seems best to me.
In C# (well, WinForms) each UI element has a Tag member into which you can put whatever you want. So, when the user presses the 'switch', the code can iterate over the controls looking for controls with a Tag that matches the current selection.
For example, suppose the LED images have the text 'LED=' in their Tag field, then you can write a function to set the glow state:
// example usage: SetGlow ("Red");
void SetGlow (string colour)
{
SetGlow (Controls, colour);
}
void SetGlow (ControlContainer controls, string colour)
{
foreach (Control control in controls)
{
if (control.Tag is a string) // syntax escapes me
{
string tag = (string) control.Tag;
if (tag.StartsWith ("LED="))
{
if (tag == ("LED=" + colour))
{
// enable glow
}
else
{
// disable glow
}
}
}
SetGlow (control.Controls, colour);
}
}
How do I populate a Form from within a method in a class library? So in the example below Method1() is what's it about.
Project "UI", Windows Forms Application
reference to MyLib
public class Form1 : Form
{
...
call some methods from MyLib.MyClass
...
}
Project "MyLib", Class Library
public class MyClass
{
...
public void Method1()
{
loop through an array and ask user to validate some data on the form during each iteration
}
}
UPDATE:
To be more specific, the MyLib library contains a class that will load a .csv file into an array (which for each row will be added to a List<string[]>) and than will loop through the List<string[]> looking for "possible" duplicates. Whenever one is found the user needs to be presented (on a Form) with both records to ultimately decide if they are the same.
How do I populate a Form from within a method in a class library?
The real question is why would you want to? The library should not be responsible for something like this. This is logic specific to your workflow and UI, not something a library is typically used for. The library should provide useful data structures, but things that are specific to your application (like gathering input and deciding what to do with it) should be handled by your code.
Anyway... I feel a bit dirty saying this... you could always just pass a reference to your form type as an argument to the method (an approach that will, among other things, tightly couple the two assemblies, making one unusable without the other)...
shudder
You may use Cross/Circular-referencing but this is not advisable due to several reasons.
You may also declare a Form-type object(better if static) within the class library and pass that form as reference and you may call the child controls within that referenced variable through the member "Controls" if I'm not mistaken.
Even though Ed put that final comment in, DO NOT DO IT! Of course it's possible, but it makes no sense. Resist the temptation!
The library should implement some general functionality, i.e. provide data structures, logic methods or maybe P/Invoke methods. But in your form class is where the logical for your UI goes. Just make a method in Form1 to handle the validation. It would be a lot easier and a lot clearer.
It's a vast question.
The easiest way would be to add a reference to System.Windows.Forms in your class lib. Then, pass the window as an argument to your business class.
But although easy this solution is, it's not a clean way. In a clean layered architecture, you can't use objects of upper layers in lowers layers. It can be both a challenge to compile and a maintenance black hole. Moreover, unit testing such cases are complex.
Considering this, another solution, a bit more complex, would be to use inversion of control, using a framework like Unity, Mef or any other, or even doing it manually.
The main idea would be to create in your class library an interface that defines user interactions like this :
public interface IInputValidator {
bool IsValid(MyClass itemToValidate);
}
Then, in you windows form application, implement this interface :
public class Form1 : Form, IInputValidator {
public void CallBusinessClass() {
var myObj = new BusinessClass(this); // the key of the concept is here
myObj.Iterate();
}
public bool IsValid(MyClass itemToValidate) {
return MessageBox.Show("Is valid ?", MessageBoxButtons.YesNo) == MessageBoxButtons.Yes);
}
}
Then, in you business class :
public class BusinessClass {
private IInputValidator m_validator;
public BusinessClass(IInputValidator validator) {
this.m_validator = validator;
}
public void Iterate()
{
foreach(var item in ItemsToIterate)
{
var isValid = m_validator.IsValid(item); // call the upper layer from a lower layer
}
}
}
hope that helps
I am trying to use selective features of two classes into 3rd class. For example, I have Button1 class which creates a fancy button border and Button2 class which writes a the text in colorful format. Now these classes are provided to me by 3rd party vendors where i dont have access to the code. The classes are not sealed so i can inherit and both are derived from the base Button class.
Now my requirement is to create a third class named Button3 class which had the functionality of both making fancy border and colorful text. Ideally, i would have inherited from both classes and used the specific functions. This is not possible in C# as it doesnt have multiple inheritence.
I was reading, that interfaces help achieve results in this case. I would request someone to guide me how to use the specific functionality of two classes in one class.
As others have said, if your application does truly need to inherit from the two UI classes given then you won't be able to do this.
More generally than with a UI, here's a to think about this:
Full inheritance implies an "is-a" kind of relationship. Your buttons with fancy borders are buttons, but they can't be buttons with fancy text.
Interfaces define a "has-a" relationship. Here you have the "ability to set a fancy border on a button" and an "ability to set fancy text on a button". In those terms there's nothing to stop you applying both "abilities" to the same button class.
So an interface lets you do aggregation. Consider two classes DoerOfThis: IThis and DoerOfThat: IThat. To create a third class Something that does both DoThis and DoThat, aggregate:
public class Something : IThis, IThat
{
public This DoerOfThis { set; }
public That DoerOfThat { set; }
public void DoThis()
{
DoerOfThis.DoThis();
}
public void DoThat()
{
DoerOfThat.DoThat();
}
}
Try to use Abstract Factory Pattern.
You can't just take random parts of different classes and combine them, even if C# had multiple inheritance. The problem is that the methods you need from each only work when they live inside the class and work together with the other methods and private state in that class. If you try to mix and match methods from one class with another they won't be able to share their internal state. So the next thing you might try is to use containment and have two copies of the internal state, but that leads to problems trying to keep them synchronized. Plus now both classes want access to the paint methods, etc. Instead of working together, they will most likely fight each other and paint over each others changes. It's difficult to get this right.
What you need to do is to take the source code for one of the two Button classes and modify it using the source code of the other Button class as inspiration (it's unlikely you can use the code directly). If you don't have access to (or the legal right to use) the source code then I'm afraid that you can't do it this way.
Your remaining options are:
Contact the authors of Button1 requesting them to add the desired features from Button2.
Contact the authors of Button2 requesting them to add the desired features from Button1.
Write a new button class yourself.
Interface just defines the method signature, but not the method body. Meaning that you still can't get the behavior in Button1 and Button2 even if you use interface.
You can ask your vendor to do the following:
Create interfaces that takes define the necessary properties for fancy button border and colorful text
Create methods that draw the fanciful button border and write the text in colorful format by taking in the interface defined above.
Then you inherit your button3 from both of the interfaces, call the above methods to do whatever that needs to be done.
In my opinion composition in combination with inheritance works when you want to simulate multiple inheritance. However when working with controls this usually not an option because you usually a control within another control.
Some options that you could look into would be
User Controls - If you are using winforms
Nested Controls - If you are using WPF.