Link to home
Start Free TrialLog in
Avatar of riscy
riscy

asked on

Window class and ordinary class, how to work together?.

I have window class which contains mostly private everything that control window form including textbox.

I have ordinary class (orginally using Console.Writeline method), which contains cutdown version of orginal code:-

using System;
namespace CBuffer{
public class CBR{      
public CBR(){}
...
....
public static void CBStart() {
uint loop=0;
while (loop<=100)
{
Console.WriteLine("CBLoop={0} : CBLoop2={1}",loop,(loop*loop))
// ********* How to transfer data into Form1 class so that private method can be used to display data within Textbox1.
loop++;      
} }

Above code is encapsulated and mostly private but will turn into public only for using Window Form1.

Looking into Window Form1

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using CBuffer;                                                            
namespace Form1 {
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.RichTextBox TextBox1;
.........

Textbox1 is the RichTextbox, where I like to put data into that form rather than Console.Writeline. This method is private hence restricted to this class.

(1) It is correct to say that CBuffer has no way to use TextBox1.
(2) The code within CBuffer need to use public class within Form1 that access to TextBox1
(3) Would Interface or Polymorphism solve the problem, please demostrate. I have not use this before.
(4) What is the best way to deal the above especially where I have more classes to add in latter.

Thanks
Avatar of purpleblob
purpleblob

1. Yes it is correct to say that with the current design CBuffer has no way to access TextBox1. You could obviouly alter the private visibility to public or you could add a property or method to your class to get the TextBox1 or you could make TextBox1 visibility internal but this assumes all the code for CBuffer and Form1 reside in the same assembly (DLL or EXE).

2. Sorry, not sure what you mean here, I think I may have answered this in 1. if not feel free to clarify.

3. You could create an interface and have a property or method public or internal (as described in 1.) but the main use of an interface is in reuse, i.e. interacting with diffierent types of objects through a known interface. With regards polymorphism well you could derive a new class from Form1 and then have a public or internal property/method (as described in 1.) but this seems a little over the top when you could just add the single property.

As an example of the interface use - if you really wanted to leave the Form1 as it is, yes you could create an interface thus:

interface IMyInterface
{
   System.Windows.Forms.RichTextBox TextBox
   {
      get;
   }
}

Obviously you'd need to derive your Form from this interface and implement the method

4. Well the best way is probably through adding a public property, however if you feel that it would be more beneficial to interact with the Form through an interface, i.e. maybe the interface will be reused elsewhere or you wish to abstract the Form code from the classes that use it then the interface is a good route.

Hope this helps
Oh sorry, there's me talking about visibility, you should probably prefix the interface example above with the keyword public :-)
Avatar of riscy

ASKER

Thank purpleblob,

Could you demostrate how the interface be used based on above program used, I still struggle to understand how to implement interface, once demostrated how it used, it might become make sense to me.

In CBR.cs, can interface call a method located in Form1.cs, where at CBR.cs able to transfer data into Form1.cs which has role of displaying data (combination of ref and value, if interface is allows to modify value via ref (more like pointer)).

I was wondering what happen to polymorphism?. Do they have role in this task.

Thank again

Riscy.
I don’t see a point of using interface here.
All you have to do is create a public property for class Form1 that returns the RichTextBox and use that one in the CBStart method.

Another thing is that the Form1 should be in the same assembly with CBuffer or Form1 should be compiled as DLL so you can reference it in CBuffer. Also you need to reference System.Windows.Forms.dll in CBuffer.

using System;
namespace CBuffer
{
      using Form1;
      class CBR
      {
            private static Form1 form;

            public CBR(){}
            
            public static void CBStart()
            {
                  uint loop=0;
                  if (form == null)
                        form = new Form1();
                  while (loop<=100)
                  {
                        form.TextBox.Text += "CBLoop="+loop+" : CBLoop2="+(loop*loop)+"\n";
                        loop++;    
                  }
                  form.ShowDialog();
            }

            [STAThread]
            static void Main(string[] args)
            {
                  CBStart();
            }
      }
}
------------------------------------------------------------------------------------------------------------------------------------

namespace Form1
{
      public class Form1 : System.Windows.Forms.Form
      {
            private System.Windows.Forms.Button button1;
            private System.Windows.Forms.RichTextBox TextBox1;

            public Form1(){}

            public System.Windows.Forms.RichTextBox TextBox
            {
                  get {return TextBox1;}
            }
      }
}
Okay an example for using an interface in the scenario you've suggested might be along the lines of...

public interface ITextBoxAccessor
{
   System.Windows.Forms.RichTextBox TextBox
   {
      get;
   }
}

now as you may know, this basically declares a signature or template (if you like) that your code will understand. So with the Form1 object you'd have the following:

public class Form1 : System.Windows.Forms.Form, ITextBoxAccessor
{
   // ... all your other code

   // implement the ITextBoxAccessor interface
   System.Windows.Forms.RichTextBox TextBox
   {
      get { return TextBox1; }
   }
}

Now from any code that wants to interact with the interface - let's say you have access to an instance of Form1 then you'd do the following (assuminging form is a variable to an instance of Form1 or implements the ITextBoxAccessor interface)

ITextBoxAccessor iface = (ITextBoxAccessor)form;
iface.TextBox.Text = "New Text";

Now in truth you may wish to check whether the form variable actually supports the interface by using the is keyword (a good idea to ensure it doesn't exception if you haven't supported the interface in more generic situations)

i.e.

if(form is ITextBoxAccessor)
{
   ITextBoxAccessor iface = (ITextBoxAccessor)form;
   iface.TextBox.Text = "New Text";
}

Also I've just re-read my earlier description of using polymorphism and it wasn't at all clear (in fact it was garbage :-) ). What we're doing with deriving Form1 from this new interface is polymorphic, just as is creating a new derived class from Form1 as a base class. So what I should have said to you is that we can use polymorphism in a couple of ways, 1. implement a known interface and 2. create a new derived class (as discussed previously) - sorry if I've confused things at all. Obviously the better of the two routes in terms of keeping code generic is to use the interface approach but really it all depends upon you requirements.

Polymorphism is basically the idea that you can interact with an object on different levels (or indeed using different interfaces). Thus we can talk to our form in terms of our new interface (i.e. make it appear to be an object of type ITextBoxAccessor) or we can talk to it as a Form1 or as any of the base classes/interfaces by simply casting to that type (as hown above).

Anyway, back to your question, basically we can declare an interface as having methods (and in C#'s case properties) now all we're doing is saying anything which implements an interface must in fact create/implement all methods of that interface. In our case we have a single property we need to implement.

"Can CBR.cs call a method in Form1.cs" - yes if pass the CBuffer an instance of the Form1 then you can use the code I've shown to get at it's interface but what you can do is - instead of passing a Form1 object which then ties your CBuffer to handling only objects of type Form1 you could pass it a System.Windows.Forms.Form or an even lower base class - so to complete the picture you might have the following within CBuffer

public void ChangeText(System.Windows.Forms.Form form)
{
   if(form is ITextBoxAccessor)
   {
      ITextBoxAccessor iface = (ITextBoxAccessor)form;
      iface.TextBox.Text = "New Text";
   }
}

Sorry it's a long answer but there's quite a few things to describe if you're not to up on the idea of interfaces etc. hope it helps
Avatar of riscy

ASKER

Dear  purpleblob

Thank, i will do some experiment on this and let you know how this progressed in next few days.

Best Wishes

Riscy

Dear brabchev

I have actually used the loop in Form1 that use public method on CBR.cs to performs calculation and then return value (via ref) back to Form1.cs which then display data, however in this case I trying to learn to understand interface and ploymorphism (sound like The Matrix movies, people changing at thier will (!)). I need to try something to click that and that in my mind.

Thank for kind contribution.

Best Wishes

Riscy.
 
Another approach is CBR to inherit Form1 class, but then you need to create an instance of CBR and you can’t use static method.

using System;
namespace CBuffer
{
      using Form1;
      class CBR : Form1
      {
            public CBR(){}
            
            public void CBStart()
            {
                  uint loop=0;
                  
                  while (loop<=100)
                  {
                        base.TextBox.Text += "CBLoop="+loop+" : CBLoop2="+(loop*loop)+"\n";
                        loop++;    
                  }
                  base.ShowDialog();
            }

            [STAThread]
            static void Main(string[] args)
            {
                  CBR cbr = new CBR();
                  cbr.CBStart();
            }
      }
}
ASKER CERTIFIED SOLUTION
Avatar of purpleblob
purpleblob

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial