Avatar billede weis Nybegynder
24. april 2007 - 22:00 Der er 42 kommentarer og
2 løsninger

Tilgå en metode fra en anden klasse

Jeg har min klasse "Form1" som indeholder alle mine labels, textboxe osv. I denne klasse har jeg også en "public void" metode der hedder "updateForm" som opdatere nogle af mine textboxe på formen udfra et array.

Mit problem kommer så når jeg en anden klasse der hedder "runClass" som skal kalde denne "updateForm" fordi klassen nu har ændret indeholde i det array jeg arbejder med og så skal textboxene opdateres (hvilket min updateForm gør for mig)

Hvordan tilgår jeg "updateForm" fra min "runClass"
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:05 #1
du kan evt lave den til public static void updateForm
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:05 #2
eller sende en reference til form1 med til klassen.
Men det kommer an på hvordan dine klasser hænger sammen.
Avatar billede weis Nybegynder
24. april 2007 - 22:08 #3
1. jeg kan ikke gøre den static

2. hvordan sender jeg en reference til form1?
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:12 #4
hvor og hvordan istantierer du runClass
Avatar billede weis Nybegynder
24. april 2007 - 22:13 #5
nu er jeg ikke helt med på hvad du mener med det, men jeg har min runClass i en seperat fil, som arbejder med det info som der er i et static array og det er alt den gør, så skal den bare kalde min metode!
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:18 #6
jojo det er jeg med på.

men du laver vel formodentlig en
runClass rc = new runClass();
Laver du den i Form1
Avatar billede weis Nybegynder
24. april 2007 - 22:19 #7
ja, den bliver lavet ved klik på en knap
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:26 #8
i din runClass har du en konstruktør
public runClass()
{
}
Der kan du lave yderligere en version:
public Form1 f1;
public runClass(Form1 fref1)
{
f1=fref1;
}

Nu kan du kalde updateForm i din metode som behandler data med:
f1.updateForm();
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:27 #9
når du kalder runClass fra form1 skal du bruge:
runClass rc = new runClass(this);
Avatar billede weis Nybegynder
24. april 2007 - 22:30 #10
jeg har ikke en der lige hedder det! strukturen er:

class runClass
{
  public static ....
  //alle metoderne
}
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:32 #11
paste din kilde kode.
Avatar billede weis Nybegynder
24. april 2007 - 22:33 #12
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;

namespace FindFiler
{
    class runClass
    {
        public static ArrayList liste = new ArrayList();

        public static bool SearchFinish = false;

        public static string dir = "";

        private static int sangId;

        public Thread newSearchThread = new Thread(new ThreadStart(ThreadFind));

        public static void ThreadFind()
        {
            sangId = 0;
            Find(dir);
        }

        public static void Find(string dir)
        {
            string[] files = Directory.GetFiles(dir, "*.mp3");
            foreach (string f in files)
            {
                MP3File mp3Info = ID3reader.ReadID3Tags(f);
                liste.Add(f + ";" + mp3Info.SongTitle + ";" + mp3Info.AlbumName + ";" + mp3Info.ArtistName + ";" + mp3Info.SongLength + ";" + sangId);
                sangId++;
            }
            string[] dirs = Directory.GetDirectories(dir);
            foreach (string d in dirs)
            {
                Find(d);
            }
            SearchFinish = true;
        }
    }
}
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:38 #13
og hvordan kalder du din metode i form1 ?
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:38 #14
altså din btn click
Avatar billede weis Nybegynder
24. april 2007 - 22:40 #15
jeg kalder min Thread her:

private void button3_Click(object sender, EventArgs e)
{
    SearchThread startSearch = new SearchThread();
    startSearch.newSearchThread.Start();
}
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:42 #16
hvordan ser din SearchThread class ud ?
Avatar billede weis Nybegynder
24. april 2007 - 22:43 #17
ahh... hehe... havde glemt at omdøbe den efter jeg rettede i det, SearchThread er den der hedder runClass nu!
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:45 #18
namespace FindFiler
{
    class runClass
    {
        public static ArrayList liste = new ArrayList();

        public static bool SearchFinish = false;

        public static string dir = "";

        private static int sangId;
        public static Form1 f1;
        public Thread newSearchThread = new Thread(new ThreadStart(ThreadFind));

        public static void ThreadFind()
        {
            sangId = 0;
            Find(dir);
        }

        public static void Find(string dir)
        {
            string[] files = Directory.GetFiles(dir, "*.mp3");
            foreach (string f in files)
            {
                MP3File mp3Info = ID3reader.ReadID3Tags(f);
                liste.Add(f + ";" + mp3Info.SongTitle + ";" + mp3Info.AlbumName + ";" + mp3Info.ArtistName + ";" + mp3Info.SongLength + ";" + sangId);
                sangId++;
            }
            string[] dirs = Directory.GetDirectories(dir);
            foreach (string d in dirs)
            {
                Find(d);
            }
            SearchFinish = true;
            f1.updateForm();
        }
    }
}
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:46 #19
private void button3_Click(object sender, EventArgs e)
{
    runClass startSearch = new runClass();
    runClass.f1 = this;
    startSearch.newSearchThread.Start();
}
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:47 #20
eller

private void button3_Click(object sender, EventArgs e)
{
    SearchThread startSearch = new SearchThread();
    startSearch.newSearchThread.Start();
while(!startSearch.SearchFinish )
{
System.Threading.Thread.Sleep(1000);
}
    updateForm();
}
Avatar billede dr_chaos Nybegynder
24. april 2007 - 22:48 #21
Håber det virker lukker ned for i aften. Tjekker lige forbi i morgen.
Avatar billede weis Nybegynder
25. april 2007 - 08:28 #22
der opstår et lille problem, jeg har i mellemtiden lavet mine textboxe om til et ListView, men jeg får stadig denne besked når jeg køre programmet:

Cross-thread operation not valid: Control 'listView1' accessed from a thread other than the thread it was created on.

min updateForm() ser sådan her ud:

public void updateForm()
        {
            listView1.BeginUpdate();
            try
            {
                listView1.Columns.Clear();
                listView1.Items.Clear();
                listView1.Columns.Add("Filnavn", 350, HorizontalAlignment.Left);
                listView1.Columns.Add("Titel", 200, HorizontalAlignment.Left);
                listView1.Columns.Add("Album", 200, HorizontalAlignment.Left);
                listView1.Columns.Add("Kunstner", 200, HorizontalAlignment.Left);
                listView1.Columns.Add("Længde", 130, HorizontalAlignment.Left);
                listView1.Columns.Add("index", 50, HorizontalAlignment.Left);
                int antal = SearchThread.liste.Count;
                for (int i = 0; i < antal; i++)
                {
                    string[] file = (SearchThread.liste[i].ToString()).Split(new Char[] { ';' });
                    //MP3File mp3File = ID3reader.ReadID3Tags(file);
                    ListViewItem item = new ListViewItem();
                    item.Text = file[0];
                    item.SubItems.Add(file[1]);
                    item.SubItems.Add(file[2]);
                    item.SubItems.Add(file[3]);
                    item.SubItems.Add(file[4]);
                    item.SubItems.Add(file[5]);
                    listView1.Items.Add(item);
                }
            }
            finally
            {
                listView1.EndUpdate();
            }
        }
Avatar billede dr_chaos Nybegynder
25. april 2007 - 09:26 #23
Hvilket af løsningsforeslagene brugte du ?
Avatar billede md_craig Nybegynder
25. april 2007 - 09:44 #24
Soe... hvorfor ikke bare bruge events? o.O
Avatar billede md_craig Nybegynder
25. april 2007 - 10:10 #25
Ville i det hele taget nok lave en hel masse om...

nede i run class laver du MP3File objecter og trækker info ud af dem til in samlet streng, en streng som du sennere splitter op for at få de enkeltståenden informationer ud hver for sig... spildt arbejde imo... fyr objecterne op istedet og spar arbejdet...

runclass til en singleton i dit tilfælde... hvis det overhovedet giver mening... (kunne man tænke sig at lave flere søgninger på samme tid?)...

her er hvad jeg nok ville lave RunClass om til..

  public class MP3File
  {
    //...
    //Din MP3File Klasse

    public override string ToString()
    {
      return "Returner en passende formatering på en MP3";
    }
  }

  public class RunClass
  {
    private static RunClass _instance = new RunClass();
    public static RunClass Instance { get { return RunClass._instance; } }
    private RunClass()
    {
    }

    public event EventHandler<EventArgs> RunClassUpdated;

    private List<MP3File> _list = new List<MP3File>();

    private bool _searchComplete;
    private string _dir;
    private int _songId = -1;
    private Thread _searchThread;

    //Exponering af Liste, gøres med alle andre fields der skal kunne tilgåes ude fra også.
    //Jeg har kun vist hvordan med List her...
    public List<MP3File> List
    {
      get { return _list; }
    }

    public void ThreadFind()
    {
      this._songId = 0;
      this.Find( new DirectoryInfo( _dir ) );
    }

    public void Find( DirectoryInfo dir )
    {
      foreach ( FileInfo f in dir.GetFiles( "*.mp3" ) )
      {
        MP3File mp3 = ID3reader.ReadID3Tags( f.Name );
        this._list.Add( mp3 );
        sangId++;
      }
      foreach ( DirectoryInfo d in dir.GetDirectories() )
      {
        this.Find( d );
      }
      SearchFinish = true;

      //Opdater her?
      this.OnRunClassUpdated(EventArgs.Empty);
    }

    private void OnRunClassUpdated( EventArgs args )
    {
      if ( this.RunClassUpdated != null )
        this.RunClassUpdated( this, args );
    }
  }


Oppe i din form kan du så nu subscribe til det event du har i din runclass:

    ...
    RunClass.Instance.RunClassUpdated += new EventHandler<EventArgs>( RunClass_RunClassUpdated );
    ...

    void RunClass_RunClassUpdated( object sender, EventArgs e )
    {
      if ( this.InvokeRequired )
      {
        this.Invoke( new System.EventHandler( this.RunClass_RunClassUpdated ), sender, e ));
      }
      else
      {
        this.UpdateForm();
      }
    }

Var lige i grove træk...
Avatar billede hmortensen Nybegynder
25. april 2007 - 11:05 #26
(Sidebemærkning)
md_craig, C# har en singleton implemation som ser sådan her ud:

public static readonly <T> Instance = new <T>();
Avatar billede weis Nybegynder
25. april 2007 - 12:45 #27
Jeg har aldrig arbejde med hjemmelavet events, så jeg skal lige have læse lidt om det først, men jeg får problemer med:

RunClass.Instance.RunClassUpdated += new System.EventHandler<EventArgs>(RunClass_RunClassUpdated);

skal der evt. et this ind foran "RunClass_RunClassUpdated"? og jeg får en Error der siger

"The type or namespace name 'EventArgs' could not be found (are you missing a using directive or an assembly reference?)"

mangler jeg en "using"
Avatar billede md_craig Nybegynder
25. april 2007 - 13:12 #28
Den ligger i System, som jeg formåder du har... ellers hjælper det typisk lige at holde musen hen over den... så kan det være den kan finde den for dig...
Avatar billede md_craig Nybegynder
25. april 2007 - 13:20 #29
hmortensen >

Der er jo 1000'inder af måder at implementere en singleton på... jeg bruger forskellige alt afhængig af situation...

Men den der kommer jeg aldrig til at bruge da jeg er direkte imod public fields...
Avatar billede hmortensen Nybegynder
25. april 2007 - 13:23 #30
Det er den måde singleton er implementeret i C#. Hvis du gør det på den måde vil den selv håndtere locks osv.
Avatar billede md_craig Nybegynder
25. april 2007 - 15:19 #31
Skal jeg også bare gentage mig selv?...

Det kan godt være det er en eller anden fantastisk smart måde den er implementeret på i C#... ændre ikke på:

a. Jeg er imod public fields...
b. Den er OVERHOVEDET ikke lazy bound...
c. Der er stadig 1000 måder at implementere en singleton på... som alle også er korekte...

DERUDOVER stemmer det du siger ikke overens med
http://msdn2.microsoft.com/en-us/library/ms998558.aspx

Selv bruger jeg typisk:
http://www.yoda.arachsys.com/csharp/singleton.html

Som reference til forskellige anvendelser...

Derudover gør:
public static readonly <T> Instance = new <T>();

Ikke en klasse til singleton i sig selv...
Jeg går derfor ud fra du referere til en der skal se således ud:

  public class SingleTon
  {
    public static readonly SingleTon Instance = new SingleTon();
    private SingleTon()
    {

    }
  }

Den er sjovt nok ikke meget anderledes end den jeg har smidt.
Avatar billede hmortensen Nybegynder
25. april 2007 - 15:31 #32
Så skal du bare læse de rigtige steder.
http://msdn2.microsoft.com/en-us/library/ms954629.aspx

public static readonly <T> Instance = new <T>();
og
public static readonly SingleTon Instance = new SingleTon();
er forskelligt hvordan?
Avatar billede md_craig Nybegynder
25. april 2007 - 15:59 #33
Det er ens?... jeg skrev jeg gik ud fra at med:
public static readonly <T> Instance = new <T>();

Mente du:
public static readonly SingleTon Instance = new SingleTon();

Men det er IKKE en singleton nogen af dem...
For der mangler en private constructor.
_______________________________________________________________________________
http://msdn2.microsoft.com/en-us/library/ms998558.aspx er forkert?...

Nej... det er begge meget korrekte måder at gøre det på... som jeg sagde tidligere er der 1000 måder at gøre det på... og din er en af dem, ingen tvivl... men det du viser er ikke MÅDEN at gøre det på i C#... det er ÉN af måderne at gøre det på i C#...
Avatar billede weis Nybegynder
25. april 2007 - 16:09 #34
kan det passe jeg skal bruge:

RunClass.Instance.RunClassUpdated += new System.EventHandler<System.EventArgs>(this.RunClass_RunClassUpdated);

for at det virker? og hvordan kalder jeg:

void RunClass_RunClassUpdated( object sender, EventArgs e )
    {
      if ( this.InvokeRequired )
      {
        this.Invoke( new System.EventHandler( this.RunClass_RunClassUpdated ), sender, e ));
      }
      else
      {
        this.UpdateForm();
      }
    }

når jeg klikker på min søgeknap???
Avatar billede weis Nybegynder
25. april 2007 - 16:14 #35
dr_chaos -->

Den løsning jeg brugte der gav fejlen: "Cross-thread operation not valid: Control 'listView1' accessed from a thread other than the thread it was created on."

var den første:

private void button3_Click(object sender, EventArgs e)
{
    runClass startSearch = new runClass();
    runClass.f1 = this;
    startSearch.newSearchThread.Start();
}

hvis der findes en løsning til den fejl, så tror jeg det vil være min fortrukne, da den vil ændre mindst i min nuværende løsning!
Avatar billede md_craig Nybegynder
25. april 2007 - 16:18 #36
weis >

void RunClass_RunClassUpdated( object sender, EventArgs e )

Bliver kaldt af dit event, dvs. nede fra din RunClass... der skal du lige finde ud af hvornår og hvor tit du vil opdatere?...

Hvis det er når søgningen er udført så er det jeg indledende gav dig fint... det er så her du kalder din void RunClass_RunClassUpdated( object sender, EventArgs e ):

    private void OnRunClassUpdated( EventArgs args )
    {
      if ( this.RunClassUpdated != null )
        this.RunClassUpdated( this, args );
    }

Men du skal selvfølgelig subscribe til eventet fra din form først... det er det du gør her:

RunClass.Instance.RunClassUpdated += new System.EventHandler<System.EventArgs>(this.RunClass_RunClassUpdated);

ok... den skal du jo så have placeret et passende sted i din form... det kunne være i constructoren eller form load...

Ved ikke om det hjælper mere?
Avatar billede md_craig Nybegynder
25. april 2007 - 16:37 #37
25/04-2007 16:14:00 >

Det er faktisk det jeg behandler med:

if ( this.InvokeRequired )
{
  this.Invoke( new System.EventHandler( this.RunClass_RunClassUpdated ), sender, e ));
}
else
{
  this.UpdateForm();
}

Du vil nemlig få samme problem med events når de rejses fra en anden tråd også...
Du skal så lige have lavet en delegate... men ja...

fx:
    public delegate void UpdaterDelegate();
    public void Update()
    {
      if(this.InvokeRequired)
        this.Invoke( new UpdaterDelegate( this.Update ) );
      else
        this.UpdateForm();
    }

der kan lige være lidt tryk/stave fejl.. men det er principet du kan bruge...

Enyways...

Princippet i det dr_chaos og events er faktisk i bund og grund det samme...
Men... alligevel ikke helt...

Er du helt nu i programmering eller har du kendskab til andre sprog?... (Java fx?)..

forestil dig du istedet for:
private void button3_Click(object sender, EventArgs e)
{
    runClass startSearch = new runClass();
    runClass.f1 = this;
    startSearch.newSearchThread.Start();
}

Gjorde:
private void button3_Click(object sender, EventArgs e)
{
    runClass startSearch = new runClass();
    runClass.AddObserver( this );
    startSearch.newSearchThread.Start();
}

Nede i din RunClass ville du nu istedet:
       
        public static List<Form1> _observers = new List<Form1>();

        public static void AddObserver( Form1 observer )
        {
          _observers.Add( observer );
        }

        public static void Find(string dir)
        {
            ...
            foreach(Form1 f in _obersvers)
              f.updateForm();
        }

Kan du se ideen i det?... du har muligheden for at flere instanser af Form1 kan blive obdateret hvis din liste opdatere sig...?...

dette ordner events bare for dig på en meget mere bekvemt måde...
Og du kan også godt have static events...

  class Program
  {
    static void Main( string[] args )
    {
      SingleTon.Update += new EventHandler<EventArgs>( SingleTon_Update );
      SingleTon.DoStuff();
    }

    static void SingleTon_Update( object sender, EventArgs e )
    {
      Console.WriteLine( SingleTon.current );
    }
  }

  public class SingleTon
  {
    public static event EventHandler<EventArgs> Update;
    public static int current;
    public static void DoStuff()
    {
      for ( int i = 0; i < 100; i++ )
      {
        current = i;
        if(SingleTon.Update != null)
          SingleTon.Update( null, EventArgs.Empty );
      }
    }
  }

fx...

Grunden til jeg lavede dit kode mere om end det... var at jeg syntes det ville give bedre mening hvis du havde en singleting frem for alle de statiske lister og fields...
Avatar billede weis Nybegynder
25. april 2007 - 19:29 #38
Lige pt virker det med events lidt uoverskueligt, så jeg tror jeg vil begynde i det små, med at kunne kalde en anden klasse, som så ændre teksten i labels osv. jeg har læse lidt på msdn om det, men findes der andre gode steder man kan læse når man vil begynde med events?
Avatar billede md_craig Nybegynder
25. april 2007 - 19:57 #39
http://www.google.co.uk/search?hl=en&q=C%23+Events&meta=

Go for it! :P..

Events er til at starte med faktisk meget simpelt efter min mening...
Som du kan se i det jeg postede oven for er der vist ikke mange linier der omhandler selve eventet ;)
Avatar billede weis Nybegynder
13. august 2007 - 22:59 #40
kom gerne med et svar
Avatar billede dr_chaos Nybegynder
14. august 2007 - 19:22 #41
hvem ?
Avatar billede weis Nybegynder
14. august 2007 - 19:33 #42
gerne begge, vil til at have spg. lukket :)
Avatar billede dr_chaos Nybegynder
14. august 2007 - 20:05 #43
svar :)
Avatar billede md_craig Nybegynder
15. august 2007 - 12:53 #44
og et her fra...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester