在经常用于 WPF 应用程序的 MVVM 模式中,这可以通过多种方式实现。以下方法可能是最简单的:
1) 当前在您的代码隐藏文件中的代码将进入一种称为“ViewModel”的类。这是一个不依赖于任何面向 UI 的对象的类,而是充当 XAML 视图的“DataContext”。两者通过 Xaml 数据绑定表达式联系起来。为了让一个类至少成为 ViewModel,它必须实现 INotifyPropertyChanged 接口。 Form1 和 Form2 背后的代码都需要放入一个实现 INotifyPropertyChanged 的类中,称为 Form1ViewModel 和 Form2ViewModel。
2) Form1ViewModel 的实例可以订阅 Form2ViewModel 实例的更改,这样每次 Form1 属性发生更改时,Form2 中的处理程序都可以捕获更改并更新它自己的匹配属性
3) Form1View.xaml 和 Form2View.xaml 可以使用双向绑定表达式分别绑定到 Form1ViewModel.cs 和 Form2ViewModels.cs 的属性,这样每次 Form1ViewModel.MyProperty 更改(感谢来自 Form2ViewModel 的更新),任何绑定到 Form1ViewModel.MyProperty 的 UI 控件都将使用视图模型属性的新值进行更新。
编辑(如何在没有 MVVM 的情况下做这种事情):
我建议创建一个测试 WPF 项目。向名为“ChildWindow”的项目添加一个新窗口。将我的所有代码粘贴到文件中后,运行项目。单击按钮以“显示子窗体”。将两个窗口分开,以便它们可以并排查看。在 MainWindows TextBox 中输入一些文本,然后观察 ChildWindow 的文本框自动更新它的文本!
MainWindow.xaml:
<Window x:Class="Wpf_2FormSync.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="82*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<TextBox Text="{Binding MyName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<Button Click="Button_Click_1" Grid.Row="1" >Show Child Form</Button>
<Button Grid.Row="2" Click="Button_Click_2" >Update Child Window</Button>
</Grid>
</Window>
MainWindow.xaml.cs:
using System;
using System.ComponentModel;
using System.Windows;
namespace Wpf_2FormSync
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ChildWindow _childWindow = null;
private string _myName = "";
public string MyName
{
get { return _myName; }
set
{
if (value == _myName) return;
_myName = value;
NotifyOfPropertyChanged("MyName");
if (_childWindow != null)
_childWindow.MyName = value;
}
}
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
_childWindow = new ChildWindow();
_childWindow.Show();
_childWindow.MyName = "John";
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyOfPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
if (_childWindow != null)
_childWindow.MyName = this.MyName;
}
}
}
ChildWindow.xaml:
<Window x:Class="Wpf_2FormSync.ChildWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ChildWindow" Height="300" Width="300" DataContext="{Binding RelativeSource={RelativeSource Self}}" >
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="112*"/>
<RowDefinition Height="157*"/>
</Grid.RowDefinitions>
<TextBox Text="{Binding MyName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0"></TextBox>
<Button Grid.Row="1" Click="Button_Click_1">Show</Button>
</Grid>
</Window>
ChildWindow.xaml.cs:
using System.ComponentModel;
using System.Windows;
namespace Wpf_2FormSync
{
/// <summary>
/// Interaction logic for ChildWindow.xaml
/// </summary>
public partial class ChildWindow : Window, INotifyPropertyChanged
{
private string _myName = "";
public string MyName
{
get { return _myName; }
set
{
if (value == _myName) return;
_myName = value;
NotifyOfPropertyChanged("MyName");
}
}
public ChildWindow()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyOfPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
MessageBox.Show(MyName);
}
}
}