topbanner_forum
  *

avatar image

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
  • Sunday December 15, 2024, 11:15 am
  • Proudly celebrating 15+ years online.
  • Donate now to become a lifetime supporting member of the site and get a non-expiring license key for all of our programs.
  • donate

Author Topic: Forms calls a class, class interacting with a form  (Read 6463 times)

mediaguycouk

  • Supporting Member
  • Joined in 2007
  • **
  • Posts: 247
    • View Profile
    • Mediaguy
    • Donate to Member
Forms calls a class, class interacting with a form
« on: November 21, 2008, 01:21 PM »
If I have a textbox in a form called 'textbox' and a class called 'class' is there any way of doing this?

Form1:
textbox.text = "";
Class class = new Class();
class.runfunction()

Class:
public void runfunction()
{
 form1.textbox.text = "Some text"; // This would never work, but how could it?
}
Learning C# - Graham Robinson

rht341

  • Participant
  • Joined in 2007
  • *
  • default avatar
  • Posts: 8
    • View Profile
    • Donate to Member
Re: Forms calls a class, class interacting with a form
« Reply #1 on: November 21, 2008, 01:47 PM »
Hello,

There is more than one way to do this; one is to have the runfunction method take a TextBox as a parameter:

Form1:
textbox.text = "";
Class class = new Class();
class.runfunction(textbox)

Class:
public void runfunction(TextBox tx)
{
 tx.text = "Some text"; // This would never work, but how could it?
}

mediaguycouk

  • Supporting Member
  • Joined in 2007
  • **
  • Posts: 247
    • View Profile
    • Mediaguy
    • Donate to Member
Re: Forms calls a class, class interacting with a form
« Reply #2 on: November 22, 2008, 11:09 AM »
I never knew that, thanks.

Is it possible to do it in the class itself (so it is usable by all functions?)

Something like Class class = new Class(textbox);
Learning C# - Graham Robinson

rht341

  • Participant
  • Joined in 2007
  • *
  • default avatar
  • Posts: 8
    • View Profile
    • Donate to Member
Re: Forms calls a class, class interacting with a form
« Reply #3 on: November 22, 2008, 12:43 PM »
Yes, you have to declare a special constructor (New) and have a private variable in the class:

Public Class MyClass
    private _tx as TextBox

    Public Sub New(ByVal txtBox as TextBox)
        _tx = txtBox
    End Sub

    Public Sub MyFunction(ByVal someText as String)
        _tx.Text = someText
    End Sub
End Class

CWuestefeld

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 1,009
    • View Profile
    • Donate to Member
Re: Forms calls a class, class interacting with a form
« Reply #4 on: November 22, 2008, 12:49 PM »
rht341 is certainly correct, but a couple of warnings:

1: In your proposal to put the reference to the textbox into your class's constructor, you've tied the life of the textbox to the life of your object. A reference to the textbox will keep it around as long as your class, and this may manifest itself as a memory leak, causing your program to die after having been active for some time.

2: In the 15-20 years that OO development has been popular, we've learned some lessons. Depending on the nature of your class, you may be about to step into one of the classic blunders. The most famous is never get involved in a land war in Asia, but only slightly less well-known is this: keep your application's data separate from its user interface. When things start to get bound together tightly, it becomes difficult to maintain your program as you need to make changes to either the UI or the data. Better to keep them separate, with a well-defined interface dictating how they interact. Probably the leading design for ensuring this is the Model-View-Controller pattern.

This same kind of question comes up in many areas, and developers have found many ways that work well for attacking them. These have been documented and gathered together in catalogs of "patterns" (e.g. here: http://www.dofactory...tterns/Patterns.aspx ). You'll give yourself a big leg up if you read up on these. You'll get the benefit of many years of experience from developers that have gone before us.

f0dder

  • Charter Honorary Member
  • Joined in 2005
  • ***
  • Posts: 9,153
  • [Well, THAT escalated quickly!]
    • View Profile
    • f0dder's place
    • Read more about this member.
    • Donate to Member
Re: Forms calls a class, class interacting with a form
« Reply #5 on: November 22, 2008, 12:58 PM »
CW: you don't get a leak from #1 unless you have a really unusual GUI design :)

Amen to #2, though. MVC 4tw.
- carpe noctem

CWuestefeld

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 1,009
    • View Profile
    • Donate to Member
Re: Forms calls a class, class interacting with a form
« Reply #6 on: November 22, 2008, 02:09 PM »
CW: you don't get a leak from #1 unless you have a really unusual GUI design :)

In .Net WinForms (which I assume is the environment, judging by the VB syntax), you will have a leak. This must be the case in any garbage-collected environment. In this example, the TextBox (and hence any handles it's using, too) cannot be collected while there are any live objects referencing them. The reference from MyClass will hold any referenced TextBox in memory until the MyClass object itself is collected.

I meant to offer a more concrete suggestion as a worthwhile and instructive step before jumping into MVC.

Declare an Event in your Class, and let your form listen for that event. This is easy to do: syntactically it's just like when your form waits for a button click or something like that. The advantage is that MyClass doesn't need to have the faintest idea of how the UI works. He just needs to shout out by way of the Event: "Hey! I've got a new value for myname (or whatever)!".

The same caveats about leaks apply, though. When you subscribe to the Event, you're holding a reference to the MyClass instance. That instance can't be garbage collected until the reference is cleared, either explicitly or by the death of the form that's listening to it.

mediaguycouk

  • Supporting Member
  • Joined in 2007
  • **
  • Posts: 247
    • View Profile
    • Mediaguy
    • Donate to Member
Re: Forms calls a class, class interacting with a form
« Reply #7 on: November 22, 2008, 02:19 PM »
Something that I have learnt, which I havn't followed here, is that I shouldn't ask direct questions. I should say what I'm doing and ask for general advise.

Here is what I'm doing...

I have a front end interface for ffmpeg. Ffmpeg is a command line video encoding. The class in this case is Ffmpeg.cs, which runs all the arguements

Code: C# [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Text;
  6. using System.Windows.Forms;
  7.  
  8. namespace H264Convert
  9. {
  10.     class Ffmpeg
  11.     {
  12.         // Where FFMPEG should be
  13.         // This is also in Form1.cs
  14.         public string ffmpegLocation = @"C:\program files\ffmpeg\ffmpeg.exe";
  15.  
  16.         // Create a new process
  17.         System.Diagnostics.Process proc = new System.Diagnostics.Process();
  18.  
  19.         // Function to actually envoke FFMPEG
  20.         public void runFFMPEG(string inputFile, string outputFile, string aspectRatio,
  21.             string dimensions, string bitRate, string passes, string videoTypeArg,
  22.             string audioFrequency, string audioBitRate, string deinterlace, string otherArgs, string audioCodec)
  23.         {
  24.             // See if the video to be output already exists
  25.             if (File.Exists(outputFile))
  26.             {
  27.                
  28.                 // and stop FFMPEG from starting
  29.                 return;
  30.             }
  31.             // Create arguements from passed variables
  32.             string arguement = " -i \"" + inputFile + "\"" +
  33.                 " -aspect " + aspectRatio +
  34.                 " -pass " + passes +
  35.                 " " + videoTypeArg +
  36.                 " -b " + bitRate +
  37.                 " -ar " + audioFrequency +
  38.                 " -ab " + audioBitRate +
  39.                 " -acodec " + audioCodec +
  40.                 " -s " + dimensions +
  41.                 " " + deinterlace +
  42.                 " " + otherArgs +
  43.                 " " + "-y" + // Overwrite
  44.                 " \"" + outputFile + "\"";
  45.  
  46.             // Stop proc raising events
  47.             proc.EnableRaisingEvents = false;
  48.             // Location of file to start (FFMPEG)
  49.             proc.StartInfo.FileName = ffmpegLocation;
  50.             // Arguements to pass to file
  51.             proc.StartInfo.Arguments = arguement;
  52.             // Use shell execute
  53.             proc.StartInfo.UseShellExecute = false;
  54.             // Don't show FFMPEG
  55.             proc.StartInfo.CreateNoWindow = false;
  56.             // Do not steal information from the FFMPEG window
  57.             proc.StartInfo.RedirectStandardOutput = false;
  58.             proc.StartInfo.RedirectStandardInput = false;
  59.             proc.StartInfo.RedirectStandardError = false;
  60.             // Start FFMPEG
  61.             proc.Start();
  62.             // Change processor priority from 'Normal' to 'Below Normal'
  63.             proc.PriorityClass = System.Diagnostics.ProcessPriorityClass.BelowNormal;
  64.             // Don't do anything else until it is done
  65.             proc.WaitForExit();
  66.             // Once FFMPEG is finished it will close. Just be sure that it is
  67.             proc.Close();
  68.             // Exit out of function
  69.             return;
  70.         }
  71.     }
  72. }

What I want is for the program to read the output from Ffmpeg.exe...

Code: C# [Select]
  1. StreamReader sr = proc.StandardError;
  2.          
  3.             while ((s = sr.ReadLine()) != null)
  4.             {
  5.                 t += s;
  6.             }
  7.  
  8.             doSomethingWith(t);

... and update a progress bar and text box based on what the streamreader reads.

So I thought I needed to pass the text box, but is there a better way?
Learning C# - Graham Robinson