-4

I have 2 forms: Form A and Form B. I also have a property field class.

Form A contains the label I want changed when a property is changed. Form B contains code that will change the property field.

Property Class Code:

 public class Controller
    {
        private static string _customerID;
        public static string customerID
        {
            get { return _customerID; }
            set
            {
                _customerID = value;
                if (_customerID != "")
                {
                    FormA.ChangeMe();
                }
            }
        }
    }

Form B Code:

    private void something_Click(object sender, SomethingEventArgs e) {
     Controller.customerID = "Cool";
}

Form A Code:

public static void ChangeMe()
        {
            var frmA = new FormA();
            MessageBox.Show("Test: " + Controller.customerID); //This works! Shows Cool
            frmA.lb2Change.Text = Controller.customerID; //This kind of works..
            MessageBox.Show("Test2: " + frmA.lb2Change.Text); //This shows the correct value. Shows Cool
        }

The property field value is passed (which I know from the MessageBox) however it does not update the value on the form label itself. Why is this? What am I doing wrong? I also believe there is a better alternative for achieving what ChangeMe() method is intended to achieve -- if so are there any suggestions?

NuWin
  • 276
  • 5
  • 15
  • As noted, since you are changing the property value on a new instance of `frmA` instead of the instance that already exists and which the user is actually using, the user does not of course see the new value. See https://stackoverflow.com/questions/32816542/c-sharp-cant-change-labels-and-button-properties-from-a-dialogbox for one of the many similar questions on Stack Overflow addressing this all-too-common error. – Peter Duniho Sep 25 '16 at 06:31
  • As far as the various objects interacting with each other, you have a variety of options, all of which avoid having each of the class's actually needing to know anything specific about the other. One option is to implement `INotifyPropertyChanged` and subscribe to `PropertyChanged` in the class where you want notification. See https://stackoverflow.com/questions/1665533/communicate-between-two-windows-forms-in-c-sharp for other suggestions. Again, there are already many questions on Stack Overflow addressing these concepts. – Peter Duniho Sep 25 '16 at 06:31

2 Answers2

1

You can do the following

  1. To define a delegate
  2. To Implement Property Change Notification

Delegate

public delegate void OnCustomerIDChanging(object sender,CancelEventArgs e);
public delegate void OnCustomerIDChanged(object sender,object value);
public class Controller
{
    private static string _customerID;
    public event OnCustomerIDChanging CustoerIDChanging;
    public event OnCustomerIDChanged CustoerIDChanged;
    public static string customerID
    {
        get { return _customerID; }
        set
        {
           // make sure that the value has a `value` and different from `_customerID`
           if(!string.IsNullOrEmpty(value) && _customerID!=value)
           {
               if(CustomerIDChanging!=null)
               {
                    var state = new CancelEventArgs();
                    // raise the event before changing and your code might reject the changes maybe due to violation of validation rule or something else
                    CustomerIDChanging(this,state);
                    // check if the code was not cancelled by the event from the from A
                    if(!state.Cancel)
                    {
                         // change the value and raise the event Changed
                         _customerID = value;
                         if(CustomerIDChanged!=null)
                             CustomerIDChanged(this,value);
                    }
               }
           }
        }
    }
}

in your Form and when you are initiating the Controller Object

var controller = new Controller();
controller.CustomerIDChanging +=(sd,args) =>{
     // here you can test if you want really to change the value or not
     // in case you want to reject the changes you can apply 
     args.Cancel = true;
};
controller.CustomerIDChanged +=(sd,args) =>{

     // here you implement the code **Changed already**
}

The above code will give you a great control over your code, also will make your controller code reusable and clean. Same result you can get by implementing INotifyPropertyChanged interface

INotifyPropertyChanged

you might have a look on this article to get more information

Monah
  • 6,714
  • 6
  • 22
  • 52
  • Can you please edit your answer and change the misspelled methods and events? – NuWin Sep 25 '16 at 06:56
  • where you mean, I added the event name and delegate as a sample, you can change the name in the way you want – Monah Sep 25 '16 at 07:05
  • For example, `public event OnCustomerIDChanging CustoerIDChanging; public event OnCustomerIDChanged CustoerIDChanged;` I believe it should be CustomerIDChanging and CustomerIDChanged. And for one of the delegate voids, one of them should be OnCustomerIDChanged, they are both OnCustomerIDChanging. – NuWin Sep 25 '16 at 07:08
  • I fixed it, kindly if you found my answer helpful, up vote it and mark it as answer – Monah Sep 25 '16 at 07:09
  • Well I find it very helpful. I have to do some tests. First test didn't work even with the changes. I appreciate the help though! – NuWin Sep 25 '16 at 07:13
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/124136/discussion-between-hadi-hassan-and-nuwin). – Monah Sep 25 '16 at 07:13
0

In your static method ChangeMe you are creating a new Form every time, you want to Change the value. Instead of that you want to change the value of an existing form. Therefor your Controller needs an instance of this FormA. Try it like this:

public class Controller
{
    //You can pass the form throught the constructor,
    //create it in constructor, ...
    private FormA frmA;

    private string _customerID;
    public string customerID
    {
        get { return _customerID; }
        set
        {
            _customerID = value;
            if (_customerID != "")
            {
                frmA.ChangeMe();
            }
        }
    }
}

Now you don´t need to be static in your FormA:

public void ChangeMe()
{
    MessageBox.Show("Test: " + Controller.customerID);
    this.lb2Change.Text = Controller.customerID;
}
Fruchtzwerg
  • 10,999
  • 12
  • 40
  • 49
  • Although your code will work, but your code is very dirty and not **reusable** and does not support code separation. IMO, you should not recommend such solution, You made the controller class strictly dependent on the `formA`, what if there are other `forms` and `user controls` and `classes` using this `controller` class? you will define all of them inside the controller class? – Monah Sep 25 '16 at 06:30
  • Basically your are correct. But NuWin is already struggeling with the static operator and instances of classes. Sure, your solution is much better but too complicatet at this point. – Fruchtzwerg Sep 25 '16 at 06:34
  • @Fruchtzwerg this actually doesn't work. I get a `System.NullReferenceException` on frmA.ChangeMe() in the controller class. – NuWin Sep 25 '16 at 07:03
  • You need to set the value of frmA first in your constructor or somewhere else. – Fruchtzwerg Sep 25 '16 at 07:23
  • @Fruchtzwerg I did exactly what you did in your answer. Also in Form B. I did this.. `var controller = new Controller(); controller.customerID = "Cool";` – NuWin Sep 25 '16 at 18:31