首页 > 解决方案 > 如何通过wcf服务更新宿主项目中的winform控件?

问题描述

我有一个客户端解决方案,它是带有一个表单和按钮“连接”(到 wcf 服务)的 Windows 窗体项目。

我还有另一个解决方案,它由 wcf 库项目(用于 wcf 服务)和 windows 窗体项目(用于主机)组成。WCF 服务实现了最简单的方法 Connect 增加计数器并调用通知客户端的回调。如何通过 wcf 服务(连接方法)更新宿主项目中的表单控件?

监控服务:

[ServiceContract(CallbackContract = typeof(IMonitoringServiceCallback))]
public interface IMonitoringService
{
    [OperationContract(IsOneWay = true)]
    void Connect(string name);
}

public interface IMonitoringServiceCallback
{
    [OperationContract(IsOneWay = true)]
    void Notify(string msg);
}

监控服务:

public class MonitoringService : IMonitoringService
{ 
    private int _registeredUsers = 0;

    public void Connect(string name)
    {
        _registeredUsers++;

        // How i should update textBox in Host form here?
        // Something like this: textBox1.Text = name; 

        var callback = OperationContext.Current.GetCallbackChannel<IMonitoringServiceCallback>();
        callback.Notify(_registeredUsers.ToString());
    }
}

主持人:

public partial class MonitoringListenerForm : Form
{
    private ServiceHost host = null;

    public MonitoringListenerForm()
    {
        InitializeComponent();
    }

    private void btnStartListen_Click(object sender, EventArgs e)
    {
        if (host == null)
        {
            host = new ServiceHost(typeof(MonitoringService));
            host.Open();

            textBox1.Text = "Host started @ " + DateTime.Now.ToString();
        }
    }

    private void btnStopListen_Click(object sender, EventArgs e)
    {
        host.Close();
        host = null;
        textBox1.Text = "Host closed @ " + DateTime.Now.ToString();
    }
}

客户:

public partial class MonitoringClientForm : Form, IMonitoringServiceCallback
{
    private InstanceContext instanceContext = null;
    private MonitoringServiceClient client = null;

    public MonitoringClientForm()
    {
        InitializeComponent();
    }

    public void Notify(string msg)
    {
        textBox1.Text = "Callback: " + msg;
    }

    private void btnConnect_Click(object sender, EventArgs e)
    {
        instanceContext = new InstanceContext(this);
        client = new MonitoringServiceClient(instanceContext);

        try
        {
            client.Connect("client1");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }         
}

更新:例如在监控监听器文本框中应显示客户端的名称,当客户端连接时。

在此处输入图像描述

标签: c#winformswcf

解决方案


Callbackcontract 可以根据你的描述使用。回调函数会调用客户端代码,将文本框中需要更新的参数放入回调函数中,并传递给客户端执行。客户端将使用从服务器端传递的参数更新文本框。

这是我的演示。使用的绑定是 wsdualhttpbinding。

       public class MonitoringService : IMonitoringService
{
    private  static int _registeredUsers = 0;

    public void Connect(string name)
    {
        _registeredUsers++;
        Console.WriteLine("success");
        var callback = OperationContext.Current.GetCallbackChannel<IMonitoringServiceCallback>();
         callback.Notify(_registeredUsers.ToString());
    }
}

这是服务器的代码。服务器端通过回调调用客户端代码并传递一个参数。客户端将获取参数并执行它。

     private void button1_Click(object sender, EventArgs e)
    {
        instanceContext = new InstanceContext(this);
        var client = new MonitoringServiceClient(instanceContext);

        try
        {
            client.Connect("client1");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form1());
    }

    public void Notify(string msg)
    {
        textBox1.Text = "Callback: "+msg;
    }

这是客户端代码。客户端实现回调。

在此处输入图像描述

这就是结果。

       public class MonitoringService : IMonitoringService
{
    private  static int _registeredUsers = 0;

    public void Connect(string name)
    {
        _registeredUsers++;
        Console.WriteLine("success");
        var callback = OperationContext.Current.GetCallbackChannel<IMonitoringServiceCallback>();
        callback.Notify("name");
    }
}

修改通知中的参数。

在此处输入图像描述

您可以通过修改 Notify 中的参数来更新客户端文本框的值。

更新

可以通过反射获取文本框的值,然后发送到客户端。

      public void Connect(string name)
    {
        var callback = OperationContext.Current.GetCallbackChannel<IMonitoringServiceCallback>();
        Form1 form = new Form1();
        Type type = typeof(Form1);
        System.Reflection.FieldInfo propertyInfo = type.GetField("textBox1");
        TextBox textBox = (TextBox)propertyInfo.GetValue(form);
        callback.Notify(textBox.Text);
    }

推荐阅读