Problem z przekazaniem parametru

0

Witam.

Mam następujący problem:

Program posiada dwie aplikacje okienkowe:

  1. Pierwsza z nich składa się z button oraz textBox i zdeklarowano w niej zmienna typu int 'metoda'.
  2. Druga składa się z przycisku button.

W jaki sposób mam przekazać parametr 'metoda' z pierwszej aplikacji do drugiej, aby za pomocą kliknięcia przycisku w drugiej aplikacji zmienic jej wartosc w pierwszej aplikacji..!?!?

Kod obu aplikacji..

public partial class Form1 : Form
{
    int metoda = 0;
    
    public Form1()
    {
        InitializeComponent();

        textBox1.Text = metoda.ToString();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 form2 = new Form2(ref metoda);
        form2.ShowDialog();
        form2.Dispose();
        textBox1.Text = metoda.ToString();
    }
}

public partial class Form2 : Form
{
    int metodaKopia;
    public Form2(ref int metoda)
    {
        metodaKopia = metoda;

        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        metodaKopia = 1;
        
        this.Close();
    }
}

Przekazanie parametru za pomocą referencji nic nie daje.. [???]

Proszę o pomoc :-)

Pozdrawiam.

Rafał (bakłażan)

0

Mam pewien pomysł na rozwiązanie problemu..

public partial class Form1 : Form
{
    int metoda = 0;
    
    public Form1()
    {
        InitializeComponent();

        textBox1.Text = metoda.ToString();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 form2 = new Form2();
        form2.ShowDialog();
        <b><span style="color: red">metoda = form2.metodaKopia;</span></b>
        form2.Dispose();
        textBox1.Text = metoda.ToString();
    }
}

public partial class Form2 : Form
{
    <b><span style="color: red">public</span></b> int metodaKopia;
    
    public Form2()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        metodaKopia = 1;
        
        this.Close();
    }
}

Działa. Ale czy jest to poprawne rozwiązanie? [???]

0

Ja bym to predzej zrobil za pomoca delegacji i Invoke, bo bezpieczniej. Cos w tym stylu:

class Form1 { private int value;

delegate void ChangeIntValue(int newValue);

private void ChangeMyValue(int newValue)
{
value = newValue;
}

public void InvokeChangeMyValue(int value)
{
Invoke(new ChangeIntValue(ChangeMyValue), new object[]{value});
}
}
//i teraz dwie mozliwosci

class Form2
{
Form1 parent;
public Form2(Form1 form)
{
parent = form;
}

onClick(...)
{
form.InvokeChangeMyValue(int);
}
}

//albo
class Form2
{
Form1.ChangeIntValue Form1Method;
public Form2(Form1.ChangeIntValue method)
{
Form1Method = method;
}

onClick(...)
{
Form1Method();
}
}


Pisane z palca, moga byc bledy (literowki, itp)
0

jeśli chcesz operować na zmiennej formularza Form1, która ma ściśle tego fomularza dotyczyć, to ja bym stworzył właściwość w Form1, która pozwoliłaby operować na właściwej zmiennej, a sposób obsługi tego - jak u Johny'ego, przez przekazania referencji do formularza typu Form1 w konstruktorze Form2 i operowanie na niej na właściwości.

lub

stworzył właściwości w obu klasach i użył sposóbu analogicznego jak Rafał - przypisanie przed Dispose().

Przekazanie parametru przez referencję nie działa, bo w konstruktorze używasz przypisania do zmiennej metodaKopia, przez co tworzysz nową kopię wartości (przypisanie dla typów wartościowych, czyli m.in. int, tworzy kopię przypisywanej wartości, dla typów referencyjnych - kopię referencji).

Pytanie do Johny'ego: co rozumiesz przez bezpieczniej w podanym przykładzie?

0

Bezpieczniej w sensie rozne watki formatek sobie nawzajem nie przeszkodza dzieki wykorzystaniu Invoke. Wiecej nakombinowane, to fakt, ale w sumie nie wyglada tak zle :)

0
johny_bravo napisał(a)

Bezpieczniej w sensie rozne watki formatek sobie nawzajem nie przeszkodza dzieki wykorzystaniu Invoke.

Formatki będą korzystać z tego samego wątku (

Program posiada dwie aplikacje okienkowe:

  • jak mniemam, patrząc po kodzie, "aplikacje" == okna == formatki).
0

Na wstępie dziękuje serdecznie za pomoc! :-)

johny_bravo napisał(a)

Ja bym to predzej zrobil za pomoca delegacji i Invoke, bo bezpieczniej.

johny_bravo napisał(a)

Bezpieczniej w sensie rozne watki formatek sobie nawzajem nie przeszkodza dzieki wykorzystaniu Invoke.

Ja wywołuję aplikacje Form2 poprzez ShowDialog(), a później szybciutko ja zamykam, zatem nie ma chyba możliwości błędu? Później kolejno przypisanie i pozbycie się Form2 -> Dispose().. jeżeli jestem w błędzie proszę o sprostowanie :-)

Rafał (bakłażan) napisał(a)

Form2 form2 = new Form2();
form2.ShowDialog();
metoda = form2.metodaKopia;
form2.Dispose();

casual coder napisał(a)

(...) ja bym stworzył właściwość w Form1 (...)

Jak ta właściwość powinna wyglądać? Mógłbyś napisać przykładowy kod?

Jeszcze raz dziękuję za pomoc :-)

0

O ile wiem na swoim przykladzie wywolywanie jednej formatki (okna) z drugiej i odwolywanie sie do siebie nawzajem zawsze generowalo bledy typu 'property cannot be accesed from another thread', wiec ja dla pewnosci wole sposob z Invoke i delegacjami. Moze czasem niepotrzebnie, ale przynajmniej spie spokojnie.

0

zbiorcza odpowiedź, może trochę przerost formy nad treścią, ale jeśli komuś to coś rozjaśni, to warto.

@Rafał: przykład w kodzie

@Johny: podobny problem był już dyskutowany http://4programmers.net/Forum/359592?h=#id359592

Poniżej kod przykładu (brak klas .Designer.cs, ale to chyba każdy jest w stanie odtworzyć - pierwsza formatka to textbox i 3 przyciski, druga - textbox i 1 przycisk).

namespace _p_108242
{
    // deklaracja delegata aktualizującego wartość z innego wątku
    public delegate void SetIntValueDelegate(int value);

    public partial class Form1 : Form
    {
        // prywatna składowa
        private int intValue;

        // @Rafał: przykład właściwości
        public int IntValue
        {
            get { return intValue; }
            set 
            { 
                intValue = value; 
                txtIntValue.Text = intValue.ToString();
            }
        }

        public Form1()
        {
            InitializeComponent();

            // w pasku tytułowym będziemy mieli info o wątku okna
            this.Text = string.Format("Thread ID: {0} ; hashcode: {1}", 
                Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.GetHashCode());

            IntValue = 1;
        }

        private void btnChangeByProperty_Click(object sender, EventArgs e)
        {
            // obsługa kliknięcia - zmiana z poziomu tego samego wątku
            // nie dostaniemy wyjątku, bo obie formatki działają w tym samym wątku
            new Form2(this, null).ShowDialog();
        }

        private void btnChangeByThread_Click(object sender, EventArgs e)
        {
            // obsługa kliknięcia - zmiana spod innego wątku, bez Invoke
            new Thread(new ThreadStart(LaunchThreadChange)).Start();
        }

        private void btnChangeByThreadInvoke_Click(object sender, EventArgs e)
        {
            // obsługa kliknięcia - zmiana spod innego wątku, poprzez Invoke
            new Thread(new ThreadStart(LaunchThreadChangeInvoke)).Start();
        }

        private void LaunchThreadChange()
        {
            btnChangeByProperty_Click(null, null);
            // przy aktualizacji z formatki dostaniemy wyjątek
        }

        private void LaunchThreadChangeInvoke()
        {
            new Form2(this, new SetIntValueDelegate(SetIntValue)).ShowDialog();
            // tu nie będzie wyjatku, bo robimy aktualizację przez Control.Invoke()
        }

        // metoda aktualizująca dla delegata
        private void SetIntValue(int value)
        {
            IntValue = value;
        }
    }
}
namespace _p_108242
{
    public partial class Form2 : Form
    {
        private Form1       parent = null;
        SetIntValueDelegate setter = null;

        public Form2(Form1 parentForm, SetIntValueDelegate setterDelegate)
        {
            InitializeComponent();

             // w pasku tytułowym będziemy mieli info o wątku okna
            this.Text = string.Format("Thread ID: {0} ; hashcode: {1}", 
                Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.GetHashCode());

            // referencja do formatki-rodzica
            parent          = parentForm;
            setter          = setterDelegate;

            txtUpdate.Text  = parent.IntValue.ToString();
        }

        private void btnUpdate_Click(object sender, EventArgs e)
        {
            if (setter == null)
                parent.IntValue         = Int16.Parse(txtUpdate.Text);
            else
                parent.Invoke(setter, new object[1] {Int16.Parse(txtUpdate.Text)} );

            Close();
        }
    }
}
0

No tak, skleroza nie boli. Rzeczywiscie chyba przesadzam z forma, ale jakos tak mi sie lepiej spi pozniej wiedzac, ze nic nie ma prawa wyskoczyc znienacka. W kazdym razie wychodzi, ze nie trzeba kombinowac jak ja :)

0

Podane jak na talerzu! :-) Wszystko jasne i przejrzyste! :-)

Dziękuję za pomoc!

Pozdrawiam.

Rafał (bakłażan)

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