【SignalR学习系列】5. SignalR WPF程序

转自:https://www.cnblogs.com/Soulless/p/7234352.html

首先创建 WPF Server 端,新建一个 WPF 项目

安装 Nuget 包

替换 MainWindows 的Xaml代码

复制代码
<Window x:Class="WPFServer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WPF SignalR Server" Height="319" Width="343  ">
    <Grid>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Button </span><span style="color: rgba(255, 0, 0, 1)">x:Name</span><span style="color: rgba(0, 0, 255, 1)">="ButtonStart"</span><span style="color: rgba(255, 0, 0, 1)"> Content</span><span style="color: rgba(0, 0, 255, 1)">="Start"</span><span style="color: rgba(255, 0, 0, 1)"> HorizontalAlignment</span><span style="color: rgba(0, 0, 255, 1)">="Left"</span><span style="color: rgba(255, 0, 0, 1)"> Margin</span><span style="color: rgba(0, 0, 255, 1)">="10,10,0,0"</span><span style="color: rgba(255, 0, 0, 1)"> VerticalAlignment</span><span style="color: rgba(0, 0, 255, 1)">="Top"</span><span style="color: rgba(255, 0, 0, 1)"> Width</span><span style="color: rgba(0, 0, 255, 1)">="100"</span><span style="color: rgba(255, 0, 0, 1)"> Click</span><span style="color: rgba(0, 0, 255, 1)">="ButtonStart_Click"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Button </span><span style="color: rgba(255, 0, 0, 1)">x:Name</span><span style="color: rgba(0, 0, 255, 1)">="ButtonStop"</span><span style="color: rgba(255, 0, 0, 1)"> Content</span><span style="color: rgba(0, 0, 255, 1)">="Stop"</span><span style="color: rgba(255, 0, 0, 1)"> HorizontalAlignment</span><span style="color: rgba(0, 0, 255, 1)">="Left"</span><span style="color: rgba(255, 0, 0, 1)"> Margin</span><span style="color: rgba(0, 0, 255, 1)">="225,10,0,0"</span><span style="color: rgba(255, 0, 0, 1)"> VerticalAlignment</span><span style="color: rgba(0, 0, 255, 1)">="Top"</span><span style="color: rgba(255, 0, 0, 1)"> Width</span><span style="color: rgba(0, 0, 255, 1)">="100"</span><span style="color: rgba(255, 0, 0, 1)"> Click</span><span style="color: rgba(0, 0, 255, 1)">="ButtonStop_Click"</span><span style="color: rgba(255, 0, 0, 1)"> IsEnabled</span><span style="color: rgba(0, 0, 255, 1)">="False"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">RichTextBox </span><span style="color: rgba(255, 0, 0, 1)">x:Name</span><span style="color: rgba(0, 0, 255, 1)">="RichTextBoxConsole"</span><span style="color: rgba(255, 0, 0, 1)"> HorizontalAlignment</span><span style="color: rgba(0, 0, 255, 1)">="Left"</span><span style="color: rgba(255, 0, 0, 1)"> Height</span><span style="color: rgba(0, 0, 255, 1)">="243"</span><span style="color: rgba(255, 0, 0, 1)"> Margin</span><span style="color: rgba(0, 0, 255, 1)">="10,35,0,0"</span><span style="color: rgba(255, 0, 0, 1)"> VerticalAlignment</span><span style="color: rgba(0, 0, 255, 1)">="Top"</span><span style="color: rgba(255, 0, 0, 1)"> Width</span><span style="color: rgba(0, 0, 255, 1)">="315"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">FlowDocument</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Paragraph</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Paragraph</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">FlowDocument</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">RichTextBox</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Grid</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

</Window>

复制代码

替换 MainWindows 后台代码

复制代码
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Hosting;
using Owin;
using System;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;

namespace WPFServer
{
/// <summary>
/// WPF host for a SignalR server. The host can stop and start the SignalR
/// server, report errors when trying to start the server on a URI where a
/// server is already being hosted, and monitor when clients connect and disconnect.
/// The hub used in this server is a simple echo service, and has the same
/// functionality as the other hubs in the SignalR Getting Started tutorials.
/// For simplicity, MVVM will not be used for this sample.
/// </summary>
public partial class MainWindow : Window
{
public IDisposable SignalR { get; set; }
const string ServerURI = “http://localhost:8080”;

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MainWindow()
    {
        InitializeComponent();
    }

    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> Calls the StartServer method with Task.Run to not
    </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> block the UI thread. 
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> ButtonStart_Click(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, RoutedEventArgs e)
    {
        WriteToConsole(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Starting server...</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
        ButtonStart.IsEnabled </span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
        Task.Run(() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> StartServer());
    }

    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> Stops the server and closes the form. Restart functionality omitted
    </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> for clarity.
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> ButtonStop_Click(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, RoutedEventArgs e)
    {
        SignalR.Dispose();
        Close();
    }

    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> Starts the server and checks for error thrown when another server is already 
    </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> running. This method is called asynchronously from Button_Start.
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> StartServer()
    {
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
        {
            SignalR </span>=<span style="color: rgba(0, 0, 0, 1)"> WebApp.Start(ServerURI);
        }
        </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (TargetInvocationException)
        {
            WriteToConsole(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">A server is already running at </span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> ServerURI);
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.Dispatcher.Invoke(() =&gt; ButtonStart.IsEnabled = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
        }
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.Dispatcher.Invoke(() =&gt; ButtonStop.IsEnabled = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
        WriteToConsole(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Server started at </span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> ServerURI);
    }
    </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)">This method adds a line to the RichTextBoxConsole control, using Dispatcher.Invoke if used
    </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> from a SignalR hub thread rather than the UI thread.</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> WriteToConsole(String message)
    {
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">(RichTextBoxConsole.CheckAccess()))
        {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.Dispatcher.Invoke(() =&gt;<span style="color: rgba(0, 0, 0, 1)">
                WriteToConsole(message)
            );
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
        }
        RichTextBoxConsole.AppendText(message </span>+ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\r</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> Used by OWIN's startup process. 
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Startup
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Configuration(IAppBuilder app)
    {
        app.UseCors(CorsOptions.AllowAll);
        app.MapSignalR();
    }
}
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> Echoes messages sent using the Send message by calling the
</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> addMessage method on the client. Also reports to the console
</span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> when clients connect and disconnect.
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyHub : Hub
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Send(<span style="color: rgba(0, 0, 255, 1)">string</span> name, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> message)
    {
        Clients.All.addMessage(name, message);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Groups.Add</span>

}
public override Task OnConnected()
{
//Use Application.Current.Dispatcher to access UI thread from outside the MainWindow class
Application.Current.Dispatcher.Invoke(() =>
((MainWindow)Application.Current.MainWindow).WriteToConsole("Client connected: " + Context.ConnectionId));

        </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">.OnConnected();
    }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> Task OnDisconnected(<span style="color: rgba(0, 0, 255, 1)">bool</span><span style="color: rgba(0, 0, 0, 1)"> ss)
    {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Use Application.Current.Dispatcher to access UI thread from outside the MainWindow class</span>
        Application.Current.Dispatcher.Invoke(() =&gt;<span style="color: rgba(0, 0, 0, 1)">
            ((MainWindow)Application.Current.MainWindow).WriteToConsole(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Client disconnected: </span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> Context.ConnectionId));

        </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">.OnDisconnected(ss);
    }
}

}

复制代码

 

 创建 WPF Client 端,新建一个 WPF 项目

 

安装 Nuget 包

 

替换 MainWindow 的前台 xmal 文件

复制代码
<Window x:Name="WPFClient" x:Class="WPFClient.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WPF SignalR Client" Height="552" Width="517" MinWidth="517" MinHeight="552" ResizeMode="CanMinimize" Closing="WPFClient_Closing">
    <Grid>
        <StackPanel x:Name="SignInPanel" Margin="10,0" MaxWidth="550">
            <Label Content="Enter user name:"/>
            <Grid>
                <TextBox x:Name="UserNameTextBox" Height="20" Margin="0,0,80,0"/>
                <Button x:Name="SignInButton" Content="Sign In" Width="75" Click="SignInButton_Click" HorizontalAlignment="Right"/>
            </Grid>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Label </span><span style="color: rgba(255, 0, 0, 1)">x:Name</span><span style="color: rgba(0, 0, 255, 1)">="StatusText"</span><span style="color: rgba(255, 0, 0, 1)"> Visibility</span><span style="color: rgba(0, 0, 255, 1)">="Collapsed"</span><span style="color: rgba(255, 0, 0, 1)"> HorizontalAlignment</span><span style="color: rgba(0, 0, 255, 1)">="Center"</span><span style="color: rgba(255, 0, 0, 1)"> Margin</span><span style="color: rgba(0, 0, 255, 1)">="0,10"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">StackPanel</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">StackPanel </span><span style="color: rgba(255, 0, 0, 1)">x:Name</span><span style="color: rgba(0, 0, 255, 1)">="ChatPanel"</span><span style="color: rgba(255, 0, 0, 1)"> Margin</span><span style="color: rgba(0, 0, 255, 1)">="10"</span><span style="color: rgba(255, 0, 0, 1)"> MaxWidth</span><span style="color: rgba(0, 0, 255, 1)">="550"</span><span style="color: rgba(255, 0, 0, 1)"> Visibility</span><span style="color: rgba(0, 0, 255, 1)">="Collapsed"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Grid</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">TextBox </span><span style="color: rgba(255, 0, 0, 1)">x:Name</span><span style="color: rgba(0, 0, 255, 1)">="TextBoxMessage"</span><span style="color: rgba(255, 0, 0, 1)"> Height</span><span style="color: rgba(0, 0, 255, 1)">="20"</span><span style="color: rgba(255, 0, 0, 1)"> TextWrapping</span><span style="color: rgba(0, 0, 255, 1)">="Wrap"</span><span style="color: rgba(255, 0, 0, 1)"> Margin</span><span style="color: rgba(0, 0, 255, 1)">="0,0,80,0"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">Button </span><span style="color: rgba(255, 0, 0, 1)">x:Name</span><span style="color: rgba(0, 0, 255, 1)">="ButtonSend"</span><span style="color: rgba(255, 0, 0, 1)"> Content</span><span style="color: rgba(0, 0, 255, 1)">="Send"</span><span style="color: rgba(255, 0, 0, 1)"> Width</span><span style="color: rgba(0, 0, 255, 1)">="75"</span><span style="color: rgba(255, 0, 0, 1)"> Height</span><span style="color: rgba(0, 0, 255, 1)">="20"</span><span style="color: rgba(255, 0, 0, 1)"> Click</span><span style="color: rgba(0, 0, 255, 1)">="ButtonSend_Click"</span><span style="color: rgba(255, 0, 0, 1)"> IsDefault</span><span style="color: rgba(0, 0, 255, 1)">="True"</span><span style="color: rgba(255, 0, 0, 1)"> IsEnabled</span><span style="color: rgba(0, 0, 255, 1)">="False"</span><span style="color: rgba(255, 0, 0, 1)"> HorizontalAlignment</span><span style="color: rgba(0, 0, 255, 1)">="Right"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Grid</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">RichTextBox </span><span style="color: rgba(255, 0, 0, 1)">x:Name</span><span style="color: rgba(0, 0, 255, 1)">="RichTextBoxConsole"</span><span style="color: rgba(255, 0, 0, 1)"> HorizontalAlignment</span><span style="color: rgba(0, 0, 255, 1)">="Left"</span><span style="color: rgba(255, 0, 0, 1)"> Height</span><span style="color: rgba(0, 0, 255, 1)">="461"</span><span style="color: rgba(255, 0, 0, 1)"> ScrollViewer.VerticalScrollBarVisibility</span><span style="color: rgba(0, 0, 255, 1)">="Auto"</span><span style="color: rgba(255, 0, 0, 1)"> Margin</span><span style="color: rgba(0, 0, 255, 1)">="0,10"</span><span style="color: rgba(255, 0, 0, 1)"> IsReadOnly</span><span style="color: rgba(0, 0, 255, 1)">="True"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">StackPanel</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">Grid</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

</Window>

复制代码

替换后台代码

复制代码
using System;
using System.Net.Http;
using System.Windows;
using Microsoft.AspNet.SignalR.Client;

namespace WPFClient
{
/// <summary>
/// SignalR client hosted in a WPF application. The client
/// lets the user pick a user name, connect to the server asynchronously
/// to not block the UI thread, and send chat messages to all connected
/// clients whether they are hosted in WinForms, WPF, or a web application.
/// For simplicity, MVVM will not be used for this sample.
/// </summary>
public partial class MainWindow : Window
{
/// <summary>
/// This name is simply added to sent messages to identify the user; this
/// sample does not include authentication.
/// </summary>
public String UserName { get; set; }
public IHubProxy HubProxy { get; set; }
const string ServerURI = “http://localhost:8080/signalr”;
public HubConnection Connection { get; set; }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MainWindow()
    {
        InitializeComponent();
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> ButtonSend_Click(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, RoutedEventArgs e)
    {
        HubProxy.Invoke(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Send</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, UserName, TextBoxMessage.Text);
        TextBoxMessage.Text </span>=<span style="color: rgba(0, 0, 0, 1)"> String.Empty;
        TextBoxMessage.Focus();
    }

    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> Creates and connects the hub connection and hub proxy. This method
    </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> is called asynchronously from SignInButton_Click.
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">async</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> ConnectAsync()
    {
        Connection </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HubConnection(ServerURI);
        Connection.Closed </span>+=<span style="color: rgba(0, 0, 0, 1)"> Connection_Closed;
        HubProxy </span>= Connection.CreateHubProxy(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">MyHub</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Handle incoming event from server: use Invoke to write to console from SignalR's thread</span>
        HubProxy.On&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>, <span style="color: rgba(0, 0, 255, 1)">string</span>&gt;(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AddMessage</span><span style="color: rgba(128, 0, 0, 1)">"</span>, (name, message) =&gt;
            <span style="color: rgba(0, 0, 255, 1)">this</span>.Dispatcher.Invoke(() =&gt;<span style="color: rgba(0, 0, 0, 1)">
                RichTextBoxConsole.AppendText(String.Format(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{0}: {1}\r</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, name, message))
            )
        );
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
        {
            </span><span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> Connection.Start();
        }
        </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (HttpRequestException)
        {
            StatusText.Content </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Unable to connect to server: Start server before connecting clients.</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">No connection: Don't enable Send button or show chat UI</span>
            <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
        }

        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Show chat UI; hide login UI</span>
        SignInPanel.Visibility =<span style="color: rgba(0, 0, 0, 1)"> Visibility.Collapsed;
        ChatPanel.Visibility </span>=<span style="color: rgba(0, 0, 0, 1)"> Visibility.Visible;
        ButtonSend.IsEnabled </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
        TextBoxMessage.Focus();
        RichTextBoxConsole.AppendText(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Connected to server at </span><span style="color: rgba(128, 0, 0, 1)">"</span> + ServerURI + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\r</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }

    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> If the server is stopped, the connection will time out after 30 seconds (default), and the 
    </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> Closed event will fire.
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Connection_Closed()
    {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Hide chat UI; show login UI</span>
        <span style="color: rgba(0, 0, 255, 1)">var</span> dispatcher =<span style="color: rgba(0, 0, 0, 1)"> Application.Current.Dispatcher;
        dispatcher.Invoke(() </span>=&gt; ChatPanel.Visibility =<span style="color: rgba(0, 0, 0, 1)"> Visibility.Collapsed);
        dispatcher.Invoke(() </span>=&gt; ButtonSend.IsEnabled = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
        dispatcher.Invoke(() </span>=&gt; StatusText.Content = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">You have been disconnected.</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
        dispatcher.Invoke(() </span>=&gt; SignInPanel.Visibility =<span style="color: rgba(0, 0, 0, 1)"> Visibility.Visible);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SignInButton_Click(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, RoutedEventArgs e)
    {
        UserName </span>=<span style="color: rgba(0, 0, 0, 1)"> UserNameTextBox.Text;
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Connect to server (use async method to avoid blocking UI thread)</span>
        <span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">String.IsNullOrEmpty(UserName))
        {
            StatusText.Visibility </span>=<span style="color: rgba(0, 0, 0, 1)"> Visibility.Visible;
            StatusText.Content </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Connecting to server...</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
            ConnectAsync();
        }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> WPFClient_Closing(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, System.ComponentModel.CancelEventArgs e)
    {
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (Connection != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
        {
            Connection.Stop();
            Connection.Dispose();
        }
    }
}

}

复制代码

 

在解决方案的属性里面,设置 Server 和 Client 端一起启动

运行查看效果

 

源代码链接:

链接: http://pan.baidu.com/s/1eRC2qVw 密码: twh3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值