在子窗口和父窗口(C#WPF)之间共享数据

在子窗口和父窗口(C#WPF)之间共享数据,c#,wpf,C#,Wpf,场景: 三种形式:主窗口、位置、校准自名(MainWindow:Window等) MainWindow创建三个对象的实例: 变量:Model变量=新模型() 职位:Positions PositionsWindow=新职位() 校准:校准校准窗口=新校准() 主窗口中的按钮用于显示和隐藏子窗口。主窗口中的表单字段更新类变量中的字段 主窗口代码: public partial class MainWindow : Window { Model Vars = new Mod

场景: 三种形式:主窗口、位置、校准自名(
MainWindow:Window
等)

MainWindow创建三个对象的实例:

  • 变量:
    Model变量=新模型()
  • 职位:
    Positions PositionsWindow=新职位()
  • 校准:
    校准校准窗口=新校准()
主窗口中的按钮用于显示和隐藏子窗口。主窗口中的表单字段更新类变量中的字段

主窗口代码:

 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;
        }
}
问题:子窗口中的表单字段如何更新父表单字段和/或类“Vars”中的字段,即从子表单向父表单传递数据并触发父表单中的操作


尝试:一个类似的问题建议通过主窗口
,例如:
位置swindow=new Positions()PositionsWindow.Show()不再有效。i、 e.它只适用于在单个方法中创建和关闭的子窗口。

我不建议在构造函数之前初始化变量。别习惯了。 我将更改三个窗口中每个窗口的构造函数:

public partial class Model : Window{
    MainWindow MW;

    Model(MainWindow MW){
        this.MW = MW;
        // other constructor stuff
    }
}
位置
校准
执行相同的操作

显然,在调用构造函数之前初始化窗口时不能使用
this
,因为仍然没有
this
要传递

因此,在主窗口中:

 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;
        }
}
公共部分类主窗口:窗口
{

Model Vars;//=new Model(this);我不建议在构造函数之前初始化变量。不要习惯于这样。 我将更改三个窗口中每个窗口的构造函数:

public partial class Model : Window{
    MainWindow MW;

    Model(MainWindow MW){
        this.MW = MW;
        // other constructor stuff
    }
}
位置
校准
执行相同的操作

显然,在调用构造函数之前初始化窗口时不能使用
this
,因为仍然没有
this
要传递

因此,在主窗口中:

 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;
        }
}
公共部分类主窗口:窗口
{

Model Vars;//=new Model(this);对我来说,最好的方法是使用基于订阅/发布者事件的方式,下面是实现方法。(我重新创建代码以便您能够理解)

1) 在子窗口中添加事件发布者

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);
    }
} 
3) 在这种情况下,当我在子窗口的文本框内键入并按下按钮时,它将出现在父窗口内的标签上

    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)
    {

    }
}
p/S:我已将ParentUpdated更改为ChildUpdated。感谢@Adrian的建设性反馈


对我来说,最好的方法是使用基于订阅/发布者事件的方式,下面是实现这一点的方法。(我重新创建代码以便您能够理解)

1) 在子窗口中添加事件发布者

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);
    }
} 
3) 在这种情况下,当我在子窗口的文本框内键入并按下按钮时,它将出现在父窗口内的标签上

    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)
    {

    }
}
p/S:我已将ParentUpdated更改为ChildUpdated。感谢@Adrian的建设性反馈


虽然这个模式在我看来是正确的,我也会这么做,但我会有点迂腐,说我会把这个事件命名为
ChildUpdated
而不是
ParentUpdated
,因为当孩子更新时,家长会订阅,然后从孩子那里收到更改的值。@Adrian是的,我同意你的说法,谢谢对于注释,我将相应地进行调整:)虽然模式在我看来是正确的,也是我将要做的,但我将有点迂腐,我将把事件命名为
ChildUpdated
not
ParentUpdated
,因为当孩子更新时,家长正在订阅,然后从chi接收更改的值ld。@Adrian是的,我同意你的意见,谢谢你的评论,我会相应地调整:)这会起作用,但会使子窗口与父窗口紧密耦合。如果你想更改父窗口显示数据的方式,这会给你带来更多的工作。如果你想在不同的父窗口上使用同一窗口,这也会成为一个问题。@Ad如果要更改父级显示数据的方式,则需要执行更多的工作。如何?父级实现一个方法,该方法更改子级要更改的内容,子级可以使用
MW.whateverMethod()
不同父窗口上的同一个窗口
。这是真的,但询问者没有说他想要。无论如何,对于复杂的应用程序,尤其是多进程的应用程序,这根本无法工作。在这种情况下,我更愿意使用WCF。他的应用程序只有多个线程(对于每个窗口)答案应该足够了。这样说,如果您不想再在主窗口上显示PositionsWindow的值,而是在CalibrationsWindow上,您必须更改PositionsWindow以在构造函数中使用CalibrationsWindow。虽然您可能认为这本身并不重要,但可以将其乘以更多窗口,然后hings变得更加困难。因此,虽然我说这会起作用并解决问题,但这并不是最好的解决方案。因为如果你一开始就能够以正确的方式做某件事,为什么要做两次呢?我们都应该做被认为是最佳实践的事情。@Adrian
你必须改变位置进行校准构造函数中的窗口
这不是真的。你不必改变你说的方式。
MainWindow
包含三个窗口的实例。如果他们想改变彼此的内容,可以让他们的父窗口(
MainWindow
)您只需添加
PositionsWindow
将调用
MW
的方法,以便
main窗口