Jak z innej klasy przekazać dane do obiektów formatki.

0

Witam,

nie mogę sobie poradzić z powyższym zadaniem. Potrzebuję wyświetlić stan licznika, który "leci" w osobnej klasie.
Startuję klasę Nonameclass w której działa sobie timer. Chciałbym wyświetlić jego wartość w textboxie, który znajduje się na formatce Form1.

Dziekuję za pomoc.


```namespace Test_CSharp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Run_Nonameclass();
        }

        private void Run_Nonameclass()
        {
            Nonameclass newNonameclass = new Nonameclass();
        }
    }
}


namespace Test_CSharp
{
    class Nonameclass
    {

        private System.Timers.Timer mycounter;
        public int cnt;
        Form1 frm = new Form1();

        public Nonameclass()
            {

            cnt = 0;

            mycounter = new System.Timers.Timer();
            mycounter.Interval = 1000;
            mycounter.Start();
            mycounter.Elapsed += mycounter_Tick;

        }

        private void mycounter_Tick(object source, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                cnt = cnt + 1;
                frm.textBox1.Text = cnt.ToString();        
            }
            catch (Exception ex)
            {
            }

        }
    }
}
0

Komendą Form1 frm = new Form1(); tworzysz referencję do nowo utworzonego obiektu Form1 czyli dublujesz sobie te formy.
Jeżeli chcesz przekazać z innej klasy coś do Form1 to musisz utworzyć w konstruktorze odwołanie do tego obiektu już istniejącego.

 public partial class Form1 : Form
  {
  public static Form1 form1;

  public Form1()
        {
            InitializeComponent();
        
           form1 = this;
        }

Potem w tej drugiej klasie

 try
            {
                cnt = cnt + 1;
                Form1.form1.textBox1.Text = cnt.ToString();        
            }
0

Ja czegoś nie rozumiem: Tworzysz Form1 w Nonameclass oraz Nonameclass w Form1. Coś tu pogmatwałeś.
Ale jeżeli masz instancję Nonameclass w Form1 i chcesz pobierać liczbę jak się zmieniła możesz do tego użyć zdarzeń:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            newNonameclass = new Nonameclass();
            newNonameclass.TextChanged += TextChanged;
            newNonameclass.StartTimer();
        }

        private void TextChanged(object sender, EventArgs e)
        {
            Dispatcher?.Invoke(() =>
            {
                MyTextBlock.Text = (sender as Nonameclass).cnt;
            });
        }

        Nonameclass newNonameclass;
        
    }
    class Nonameclass
    {
        private System.Timers.Timer mycounter;
        public int cnt { get; private set; }
        public Nonameclass()
        {
            cnt = 0;
           
            
        }
        public void StartTimer()
        {
            mycounter = new System.Timers.Timer();
            mycounter.Interval = 1000;
            mycounter.Elapsed += mycounter_Tick;
            mycounter.Start();
        }
        public event EventHandler<EventArgs> TextChanged;
        private void mycounter_Tick(object source, System.Timers.ElapsedEventArgs e)
        {
            ++cnt;
            TextChanged?.Invoke(this, EventArgs.Empty);
        }
    }
0

@Marik10: Dzięki za podjęcie tematu Marik10. Właśnie zrobiłem próbę, ale niestety nie poszło.
Coś dalej mam źle.

prtscr1.png

0

Było wiele razy nie można zmieniać stanu UI bezpośrednio z innego wątku. Trzeba użyć Invoke. Poszperaj

0

@jacek.placek: No właśnie szperam i wyszperać nie mogę. Cały czas wyrzuca mi błędy.

Pozdrawiam

0

@gswidwa1: Serdeczne dzięki za odpowiedź.
Chyba tego jednak nie ogarnę.
prtscr2.png

0

Form1.form1.Invoke=>(Form1.form1.textBox1.Text = cnt.ToString());
Jakoś tak to leciało.

1

Piszesz coś na czuja zupełnie bez sensu. Musisz poczytać i zrozumieć zdarzenia i delegaty bo to są podstawy.

Zdefiniuj klasę danych zdarzenia

public class TextChangedEventArgs
{
	public string Text { get; set; }
}

Nonameclass, podobnie jak u Ciebie, ma delegat i event, oraz metody start i stop do uruchamiania i zatrzymywanie timera. W timer_elapsed event wyzwalany jest z obiektem TextChangedEventArgs.

public class Nonameclass
{
	public delegate void TextChangedEventHandler(object sender, TextChangedEventArgs e);
	public event TextChangedEventHandler OnTextChanged;

	private int counter { get; set; } = 0;


	System.Timers.Timer timer = null;
	public Nonameclass()
	{
		timer = new System.Timers.Timer();
		timer.Elapsed += timer_elapsed;
		timer.Interval = 1000;
		
	}

	public void Start()
	{
		timer.Start();
	}

	public void Stop()
	{
		timer.Stop();
	}

	private void timer_elapsed(object sender, ElapsedEventArgs e)
	{
		counter++;
		this?.OnTextChanged(this, new TextChangedEventArgs { Text = $"text changed {counter}" });
	}
}

W Form jest label1 i 2 przyciski Start i Stop

public partial class Form1 : Form
    {
		Nonameclass t = new Nonameclass();

        public Form1()
        {
            InitializeComponent();
            t.OnTextChanged += T_OnTextChanged;
        }

        private void T_OnTextChanged(object sender, TextChangedEventArgs e)
        {
			this.Invoke((MethodInvoker)delegate() { label1.Text = e.Text; });
            
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
			t.Start();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
			t.Stop();
        }
    }
0

Witam ponownie,

zrobiłem coś takiego, podpatrując jeden przykład na forum. Trochę "na około" i nie do końca pewnie zgodnie ze sztuką, ale działa. Z klasy Nonameclass zrobiłem formatkę. I generalnie jestem w stanie wywoływać teraz procedurę write_to_textbox, która znajduje się w 'obrębie' docelowej formatki i przepisywać wartość licznika z klasy Nonameclass. Nie rozumiem tylko jednej rzeczy. Jeśli dodam na formatkę przycisk z na zasadzie drag and drop, to zdarzenie kliknięcia na nim prawidłowo przepisuje mi wartość licznika, który sobie gdzieś tam w tle leci. Natomiast timer 'mycounter' wrzucony tak jak to zrobiłem powoduje komunikat 'System.InvalidOperationException', mimo tego, że działa i modyfikuje zmienną cnt. Zrobiłem jeszcze jedną próbę, i wrzuciłem timer na zasadzie drag and drop (tak jak przycisk). I on też działa prawidłowo. Jaka jest różnica pomiędzy oba timerami?

Pozdrawiam Wszystkich obecnych!


using System;
using System.Windows.Forms;

namespace Test_CSharp
{
    public partial class Form1 : Form
    {
 
        private Nonameclass newNonameclass;

        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            Run_Nonameclass();
        }

        private void Run_Nonameclass()
        {
            newNonameclass = new Nonameclass(this);
            newNonameclass.Show();
            System.Threading.Thread.Sleep(500);
        }

        public void write_to_textbox(string text)
        {
                this.textBox2.Text = text;
        }

        public void write_to_textbox2(string text)
        {
            this.textBox3.Text = text;
        }

    }
}


using System;
using System.Windows.Forms;

namespace Test_CSharp
{
    public partial class Nonameclass: Form
    {

        public System.Timers.Timer mycounter;
        public int cnt;
        public int cnt2;
        private Button button1;
        private Timer timer1;
        private System.ComponentModel.IContainer components;
        private Form1 virtualform;

        public Nonameclass(Form1 virtualform)
        {
            InitializeComponent();
            this.virtualform = virtualform;
            cnt = 0;

            mycounter = new System.Timers.Timer();
            mycounter.Interval = 1000;
            mycounter.Start();
            mycounter.Elapsed += mycounter_Tick;

        }

        private void mycounter_Tick(object source, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                cnt = cnt + 1;
                virtualform.write_to_textbox(cnt.ToString());
            }
            catch (Exception ex)
            {
            }
        }

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.button1 = new System.Windows.Forms.Button();
            this.timer1 = new System.Windows.Forms.Timer(this.components);
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(37, 51);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(121, 54);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // timer1
            // 
            this.timer1.Enabled = true;
            this.timer1.Interval = 1000;
            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
            // 
            // Nonameclass
            // 
            this.ClientSize = new System.Drawing.Size(274, 229);
            this.Controls.Add(this.button1);
            this.Name = "Nonameclass";
            this.Load += new System.EventHandler(this.Nonameclass_Load);
            this.ResumeLayout(false);

        }

        private void button1_Click(object sender, EventArgs e)
        {
            virtualform.write_to_textbox(cnt.ToString());
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                cnt2 = cnt2 + 1;
                virtualform.write_to_textbox2(cnt.ToString());
            }
            catch (Exception ex)
            {
            }
        }

    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1