I need to write the result of my query in a textbox in the main form, from another class. What is the best and easy way to achieve this?
Your external class should not know anything about a textbox. It may know about your form in order to send the result there, but the elements are belong to the form and should not be exposed (it is what is called encapsulation).
I suggest you to have a meaningful method on your form, something like ShowListOfUsers(users), or whatever you do, call it appropriately so it can be understood externally.
Then in this method you put the result into the controls (textbox) as you want it.
I also suggest you to have an interface for the form which will contain such behavioral methods and have your window implemented this interface, something like:
public interface IOrderView
{
void ShowOrderDiscount(result);
}
so your external class will know only about the interface, not about the window, the textbox, etc.
Now your query component is trivial:
public class SomeOperation
{
private readonly IOrderView _view;
public SomeOperation(IOrderView view)
{
_view = view;
}
public void DoSomething(parameters)
{
var result = GetMyComplicatedResult();
_view.ShowResult(result);
}
}
The code above is not ideal (as I don't know what is your scenario), but the idea is there.
Good Luck.
Use a public property (or a getter) in your class to retrieve the output of the query.
Related
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 a Form class
partial class ProgressMainForm : Form
{
public ProgressMainForm()
{
InitializeComponent();
}
}
And then a class that uses that class and contains all functionality for the user
public class ProgressForm
{
public ProgressMainForm myProgressForm;
public ProgressForm(string title)
{
myProgressForm = new ProgressMainForm();
myProgressForm.Text = title;
}
public void SetProgressBar(int min, int max)
{
....
}
I then use this ProgressForm class in my project like this
progresswindow = new ProgressForm("Replacing All Strings");
This way progresswindow only contains members that are related to the functionality of the ProgressForm and all those Form members are hidden from the user.
But sometimes I need to access those Form members, for example when I need Invoke method.
Is there a way to make myProgressForm in ProgressForm accessible to users without making ProgressMainForm public?
Or is this approach wrong?
In my opinion you should not work with the form directly. If I read your setup correctly, you want to show progress indicator while some job is being done. ProgressForm should expose methods to set the counters and increment them; as you run it on another thread, form manipulation should be done from inside the methods of ProgressForm. Your Invokes belong there, wrapped in suitable methods. If you want to change some visual properties of ProgressMainForm relay those properties to ProgressForm.
To resume, calling code should have no clue what ProgressForm does other than setting progress boundaries, starting, setting current percentage and stopping. This way, if you are asked to port the application to another UI system the amount of code you will need to change will be drastically reduced.
Is there a way to make myProgressForm in ProgressForm accessible to users without making ProgressMainForm public?
Yes, you can create some public properties on ProgressForm that expose specific properties of ProgressMainForm.
private ProgressMainForm myProgressForm;
public int SomeProperty
{
get { return myProgressForm.IntProp; }
set { myProgressForm.IntProp = value; }
}
For readonly properties, omit the set, and for any types that are reference types, you may want to return a clone or copy (to ensure the client can't change it).
Wrap or Expose the Methods you need. But somehow i don't like the approach, restricting the access is not a bad idea but should not be the whole purpose of this kind of abstraction. Try to make the acess easier, not restrictive.
You can declare the methods as internal , This will allow you to call the methods from within the assembly.
I'm very new to using C#. If you have ever heard of the Karol the robot program that is written in Java then that's what I'm aiming to build.
But I am stumbling at almost the first hurdle, I want to make a class for Karol (It is just a picture) that can move around the screen in blocks of 32x32 squares.
Trouble is when you create a class you can't access the properties of form objects because they are separate things.
I would like to be able to manipulate form objects from my class but without having to pass the object through the method each time I use it.
Any help is much appreciated.
Do not need to pass a reference of the Form every time. Should be enough to do something like this:
`public class Karol
{
private Form _form=null;
public Karol(Form frm) {
_form = frm;
}
// after use _form inside the functions and properties of the class, where needed
}`
edit
to acces a control data inside a Form it needs to expose or controls itself, like
public Label MyFormLabel {....}
Or expose a functions/properties that sets or gets the data from the control.
public string MyFormLabelText { get{ return label.Text;} set{label.Text = value;}}
If it's just one form object that "Karol" is manipulating, you should be able to pass it to the constructor and save it for use in later member calls. That way you only pass it once at construction time.
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 have a kind of weird situation ...
I have a User Control in WPF witch in turn has some other User Controls attached to it, then I have a huge C# code file with a big algorithm which needs access to the User Control UI Elements and methods, this hole process works with a Timer which sends data to the C# code file algorithm from the User Control and it needs to return and update the UI elements from the control and also to access it's methods...
Now the thing is I don't want to put this huge algorithm in the codebehind file of my control, instead I would like to access the control's UI elements and declared methods from that code file ...
What I tried so far is to actually derive the code file's class from the User Control I use, this works fine and dandy but to access the derived class I need to create a new object of it and the UI that I get shown does not get updated since it also creates a new base class object I believe ...
so I have something like:
public partial class usrctrlSimulator : UserControl
{
public usrctrlSimulator()
{
this.InitializeComponent();
}
public void StartSimulator()
{
Algorithm = new csAlgorithm();
Algorithm.InitializeSimulator();
timer1.Start();
}
}
public class csAlgorithm : usrctrlSimulator
{
public csAlgorithm()
{
}
public void InitializeSimulator()
{
txtblkSimulatorStatus.Text = "Started"; // this element would be from the user control
}
}
So my question is : how do I call the derived class without instantiating a new object of it, since that will cause a new user control object to be created and the displayed UI will not be updated ... or if I don't derive the Algorithm class, what possibility do I have to access the user control elements and methods ?
If you want to stick with one instance of the control and still have access to the functionality in the derived class then you need to use the derived class as the control. So instead of an instance of usrctrlSimulator, you'd use csAlgorithm everywhere.
However, I'm not sure whether this design is the best approach in your scenario. The algorithm is not really a user control so maybe deriving from usrctrlSimulator is not the ideal option. For example: UserControl has a method called ApplyTemplate(). What would be the meaning of this in csAlgorithm? You can also look at it from a different angle: Would it be reasonable to use csAlgorithm wherever you could use UserControl, e.g. when invoking UserControl.AddLogicalChild(csAlgorithm)?
A different option would be to instantiate the algorithm as a member variable in usrctrlSimulator (composite). In that case you could still use it inside the usrctrlSimulator but you would have a clear separation of two concepts: A UserControl on one hand, and the implementation of an algorithm on the other hand. In addition you could then change either one of them with only limited impact on the other.
In that case your code would look as follows:
public partial class usrctrlSimulator : UserControl
{
public usrctrlSimulator()
{
this.InitializeComponent();
}
public void StartSimulator()
{
_algorithm= new csAlgorithm();
_algorithm.InitializeSimulator();
timer1.Start();
}
private csAlgorithm _algorithm;
}
public class csAlgorithm // not a UserControl anymore
{
public csAlgorithm()
{
}
public void InitializeSimulator()
{
txtblkSimulatorStatus.Text = "Started"; // this element would be from the user control
}
}