本文演示了基于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));