简体   繁体   中英

Sharing data between child and parent windows (C# WPF)

Scenario: Three forms: MainWindow, Positions, Calibration self-named ( MainWindow : Window etc.)

MainWindow creates an instance of three objects:

  • Vars: Model Vars = new Model();
  • Positions: Positions PositionsWindow = new Positions();
  • Calibration: Calibration CalibrationWindow = new Calibration();

A button in MainWindow is used to Show and Hide the child windows. Form fields in MainWindow update fields in class Vars.

MainWindow code:

 public partial class MainWindow : Window
 {

        Model Vars = new Model();
        Positions PositionsWindow = new Positions();
        Calibration CalibrationWindow = new Calibration();

        private void OpenButton_Click(object sender, RoutedEventArgs e)
        {
                PositionsWindow.Show();
        }

        private void TextBoxUpdate_Click(object sender, RoutedEventArgs e)
        {
                Vars.TestVar = TestBox.Text;
        }
}

Question: How can form fields in the child windows update the parent form fields and/or fields in the class "Vars", ie passing data from child to parent and trigger an action in the parent form?

Attempts: A similar question suggested passing the main window this , example: Positions PositionsWindow = new Positions(); however, this only works when the object is created in a method. At this point, PositionsWindow.Show(); is no longer valid. ie it is only suitable for a child window created and closed in a single method.

I would not really recommend initializing the variables before the constructor. Don't get used to that. I would change the constructor of each of the three Windows:

public partial class Model : Window{
    MainWindow MW;

    Model(MainWindow MW){
        this.MW = MW;
        // other constructor stuff
    }
}

Do the same thing for Positions and Calibration .

Obviously, you cannot use this when you are INITIALIZING the Windows BEFORE the constructor is called, because there is still no this to pass.

Therefore, in your MainWindow:

 public partial class MainWindow : Window
 {

        Model Vars; // = new Model(this); <- the constructor was not yet called, there is no this
        Positions PositionsWindow; // = new Positions();
        Calibration CalibrationWindow; // = new Calibration();

        MainWindow(){
            Vars = new Model(this);
            Positions = new Positions(this);
            CalibrationWindow = new Calibration(this);
        }

        private void OpenButton_Click(object sender, RoutedEventArgs e)
        {
                PositionsWindow.Show();
        }

        private void TextBoxUpdate_Click(object sender, RoutedEventArgs e)
        {
                Vars.TestVar = TestBox.Text;
        }
}

Edit: (to complete the answer to the question): Now, if you want the Windows to change stuff to each other, just create functions in MainWindow that change stuff in each of the Windows. And with MW you can call these functions from any child Window

For me the best is using Subscribe/Publisher event-based way, here is the way to do it. (i recreate the code so that you can understand)

1) add an event publisher in your child windows.

public partial class ChildWindows : Window
{
    // the is the event publisher
    public event Action<string> ChildUpdated;

    public ChildWindows()
    {
        InitializeComponent();
    }

    private void updateParentBtn_Click(object sender, RoutedEventArgs e)
    {
        // pass the parameter.
        ChildUpdated(updateTb.Text);
    }
} 

2) Subscribe the publisher in your parent windows.

    public partial class MainWindow : Window
{
    Model Vars;
    ChildWindows childWindows;
    public MainWindow()
    {
        InitializeComponent();
        Vars = new Model();
        childWindows = new ChildWindows();

        //this is the event subscriber.
        childWindows.ChildUpdated += ChildWindows_ChildUpdated;
    }

    //do whatever you want here.
    void ChildWindows_ChildUpdated(string obj)
    {
        // Update your Vars and parent
        Vars.TestVar = obj;
        updateLbl.Content = Vars.TestVar;
    }

    private void openButton_Click(object sender, RoutedEventArgs e)
    {
        childWindows.Show();
    }

    private void textBoxUpdate_Click(object sender, RoutedEventArgs e)
    {

    }
}

3) In this case, when i type inside the textbox in my child windows, and press a button, it will appear on a label inside my parent windows.

P/S : i had changed the ParentUpdated to ChildUpdated. thanks to @Adrian for constructive feedback

example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM