本文演示了基于WCF的进程间属性同步的流程
进程间通讯的数据模型#
视图模型 - TestViewModel#
public class TestViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
static public TestViewModel Instance = new TestViewModel();
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if (!Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
return false;
}
public void RaiseMemberChanged(string memberName)
{
MemberChangedManager.Instance.RaiseInstanceMemberChanged(this, memberName);
}
private string propertyOne;
public string PropertyOne { get => propertyOne; set => SetProperty(ref propertyOne, value); }
public string FieldOne;
}普通类 - MyClass#
[DataContract]
public class MyClass
{
static public MyClass Instance { get; private set; } = new MyClass();
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if (!Equals(field, newValue))
{
field = newValue;
RaiseMemberChanged(propertyName);
return true;
}
return false;
}
public void RaiseMemberChanged(string memberName)
{
MemberChangedManager.Instance.RaiseInstanceMemberChanged(this, memberName);
}
private string propertyOne;
public string PropertyOne { get => propertyOne; set => SetProperty(ref propertyOne, value); }
public string FieldOne;
}静态类 - MyClassStatic#
public static class MyClassStatic
{
static bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if (!Equals(field, newValue))
{
field = newValue;
RaiseMemberChanged(propertyName);
return true;
}
return false;
}
private static string propertyOne;
public static string PropertyOne { get => propertyOne; set => SetProperty(ref propertyOne, value); }
public static string FieldOne;
public static void RaiseMemberChanged(string memberName)
{
MemberChangedManager.Instance.RaiseStaticMemberChanged(typeof(MyClassStatic), memberName);
}
}视图模型的进程间同步#
注册实例#
将需要同步的视图模型实例通过以下方法注册到框架
RegisterInstance(TestViewModel.Instance);属性同步#
对于完整属性,由于在 set 方法中触发了 PropertyChanged 事件,框架会自动处理进程间的同步。
而且由于实现了 INotifyPropertyChanged 接口,视图也会同步更新。
字段同步#
对于字段,则需要手动调用以下方法通知框架,由框架处理进程间的同步。
TestViewModel.Instance.RaiseMemberChanged(nameof(TestViewModel.Instance.FieldOne));历史同步#
对于后上线的客户端,或者客户端崩溃后重启,可以通过以下方法同步在服务端保存的所有同步历史
PullMemberChangedHistory();演示#

视图#
演示的界面代码如下:
<GroupBox Header="TestViewModel">
<StackPanel DataContext="{x:Static local:TestViewModel.Instance}">
<TextBox Text="{Binding PropertyOne, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="TestViewModelFieldOne" Text="{Binding FieldOne}"/>
</StackPanel>
</GroupBox>推送#
演示中推送所做的事情如下:
// 获取界面的值
TestViewModel.Instance.FieldOne = TestViewModelFieldOne.Text;
// 通知框架
TestViewModel.Instance.RaiseMemberChanged(nameof(TestViewModel.Instance.FieldOne));刷新#
演示中刷新所做的事情如下:
// 将最新值更新到视图
TestViewModelFieldOne.Text = TestViewModel.Instance.FieldOne;普通类的进程间同步#
普通类与视图模型的进程间同步没有区别,需要注意的是如果属性不是完整属性,需要手动通知框架。
如果需要更新视图,建议使用视图模型,或者手动更新视图。
静态类的进程间同步#
静态类的进程间同步仅注册部分有区别,其他部分同视图模型的进程间同步。
注册静态类#
将需要同步的静态类通过以下方法注册到框架
RegisterStatic(typeof(MyClassStatic));