Showing posts with label WPF. Show all posts
Showing posts with label WPF. Show all posts

Saturday, August 29, 2015

Visual Studio XAML tips and tricks

I am learning the new Universal Windows Application platform and along the way I learned these XAML editing features and I am sharing these as tips and tricks.

Tip 1 – Code formatting – Position each attribute on a separate line

As a personal preference I don’t like to scroll left and right just to see the all the attribute values of a XAML element. So to have each attribute value pair appear on a separate line you can go to Options > Text Editor > XAML > Formatting > Spacing  and select Position each attribute on a separate line. Enjoy.

image

Converts this

 image

into this

image

Tip 2 – View XAML Design page on one screen and XAML code page on another screen.

As a web developer I am so spoiled by always having code on one screen and browser on other screen. Edit code and hit refresh on other screen. I don’t like that XAML code and design page are stacked on top of each other. The view is very small and difficult to work with. I would love if there was an easy way to unpin the code and pin it to a secondary screen. 

Open your desired XAML file.  I am using MainPage.xaml. Its opens. Cool !! now to open it on the second screen right click your XAML page and Click on Open With option.

image

And then choose XML (Text) Editor option and XAML page will open. Now you should have same two files open and you can take the XAML page which as Design/XAML options available at the bottom like shown in screenshot below and double click on the Design option.  This will take the Design view to full screen but still have your XAML code window as is.

image

Now unpin the design window and drag and drop to second screen so when you edit your XAML code the design gets updated in real time on the second screen. I like this feature but this should be easier.

Tip 3 – Live Visual Tree

This is the best addition to Visual Studio 2015. While above two tips should work with older VS versions this one requires VS2015.  Just like F12 developer tools in browsers you can select any element by hovering mouse over it or select any element in the tree view to see which element is selected on the view you can do similar stuff with XAML now. My favorite thing in this feature is when you click on any element in the tree view and click on show properties then Properties window appears. The Properties window shows you all the properties that were applied to each element and you can change them and see the output in real time. You can also see some properties that are not applied or overridden as striked out.  Another cool thing with this feature is that as you select each element you can see XAML source view being updated. This is awesome.  Good job XAML team !!  I was able to fix my three column layout easily by using this feature.

If you know any cool XAML features that you love please share by leaving comments below.

Saturday, December 1, 2012

SignalR in Web, WPF, Console and Windows Services App in VB


Update: I have updated this post to reflect the latest SignalR (1.0.1) release.  This is some testing I did with SignalR in VB for different kinds of .Net projects like Windows Service, console and WPF application.  This post has different sections and each section has its own .Net solution so you can run them individually.  All the sourcecode for this blog post is available on my github page.  There are two SignalR Owin Host applications, a Console application and a Windows Services Application written in Vb.NET and it will be consumed by various .NET client applications such as Console Application, Web Application using Javascript, WPF Application using VB.Net.

SignalR Owin Hosts
    Console Application
    Windows Services Application
SignalR Owin Clients
    Console Application
       Web Application
       WPF Application

So let’s get started by first creating our SignalR Owin Host Console Application. 

SignalR Server Console Application in VB
Create a console application in VB and Install following nuget packages using Package Manager Console to create SignalR Hub.

>Install-Package Microsoft.Aspnet. Owin.Hosting -pre
>Install-Package Microsoft.Aspnet. Owin.Host.HttpListener -pre
>Install-Package Microsoft.Aspnet.Signalr.Owin

Without further due here is the code to start the server and create a hub which will start sending messages to clients upon arrival.
---------------------------------------
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Hubs
Imports Microsoft.Owin.Hosting
Imports Owin
Module Module1
    Sub Main()
        Dim url As String = "http://localhost:8080/"
        Using WebApplication.Start(Of Startup)(url)
            Console.ForegroundColor = ConsoleColor.Green
            Console.WriteLine("Server running on {0}", url)
            Console.WriteLine("Press any key to start sending events to connected clients")
            Console.ReadLine()
            Dim context As IHubContext = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
            For x As Integer = 0 To 100
                System.Threading.Thread.Sleep(3000)
                Console.WriteLine("Server Sending Value to Client X: " + x.ToString())
                context.Clients.All.addMessage(x.ToString())
            Next
            Console.ReadLine()
        End Using
    End Sub
    Public Class Startup
        Public Sub Configuration(ByVal app As IAppBuilder)
            Dim config = New HubConfiguration With {.EnableCrossDomain = True}
            app.MapHubs(config)
        End Sub
    End Class
    <HubName("myHub")> _
    Public Class MyHub
        Inherits Hub
        Public Sub Chatter(param As String)
            Console.WriteLine(param)
            Clients.All.addMessage(param)
        End Sub
    End Class
End Module
-----------------------------------------------
 IHubContext will give you access to all the clients and then you can communicate to all the clients. When you run this application you will see the following screenshot.  Once you have your client code written then you can press any key and it will start sending values to connected clients. 


Now lets consume this Self Host in a Client Console Application. 
SignalR Client Console Application in VB.  
Create a Console Application in VB and install nuget package using Package Manager Console. 

>Install-Package Microsoft.Aspnet.Signalr.Client

Then paste the following code into your Module1.vb page.  And run the application assuming you have already started the host application.

--------------------------------------
Imports Microsoft.AspNet.SignalR.Client.Hubs
Imports Microsoft.AspNet.SignalR
Module Module1

    Sub Main()
        Dim connection = New HubConnection("http://localhost:8080")

        Dim myHub = connection.CreateHubProxy("myHub")

        connection.Start().Wait()
        Console.ForegroundColor = ConsoleColor.Yellow
        myHub.Invoke(Of String)("chatter", "Hi!! Server") _
        .ContinueWith(
            Sub(task)
                If task.IsFaulted Then
                    Console.WriteLine("Could not Invoke the server method Chatter: {0}", _
                                      task.Exception.GetBaseException())
                Else
                    Console.WriteLine("Success calling chatter method")
                End If
            End Sub)

        myHub.On(Of String)("addMessage", _
            Sub(param)
                Console.WriteLine("Client receiving value from server: {0}", param.ToString())
            End Sub)
        Console.ReadLine()
    End Sub
End Module
-----------------------------------

Now it is time to test our application.  Run our application side by side.  I have server or host running on the left hand side with green color text and client running on the right with yellow color text.


When the client application is started, it invokes the chatter method on the server. 
  
      myHub.Invoke(Of String)("chatter", "Hi!! Server") _
        .ContinueWith(
            Sub(task)
                If task.IsFaulted Then
                    Console.WriteLine("Could not Invoke the server method Chatter: {0}", _
                                      task.Exception.GetBaseException())
                Else
                    Console.WriteLine("Success calling chatter method")
                End If
            End Sub)

You will see “Hi!! Server” value received by the server on the left.  That value is again round tripped to the client and you can see it displayed by the client on the right hand side. 

  myHub.On(Of String)("addMessage", _
            Sub(param)
                Console.WriteLine("Client receiving value from server: {0}", param.ToString())
            End Sub)

Now click on the server console window and press any key.  It will start sending value to the client in real time.  We do this by first getting IHubContext object which knows about all the clients.

            Dim context As IHubContext = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
            For x As Integer = 0 To 100
                System.Threading.Thread.Sleep(3000)

                Console.WriteLine("Server Sending Value to Client X: " + x.ToString())
                context.Clients.All.addMessage(x.ToString())
            Next



Now let’s create some more clients that will work with our SignalR Owin Host Console Application. 

SignalR Client WPF Application in VB 
Create a WPF Application in VB and install the following package using Package Manager Console.

>Install-Package Microsoft.AspNet.SignalR.Client.

XAML Side
When you create a WPF application by default MainWindow.xaml file is opened and there paste the following code.  There is a button which will invoke Chatter method on the server. 

<Window x:Class="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" Loaded="MainWindow_Loaded" >
    <ScrollViewer>
        <StackPanel>
            <Button x:Name="btnShowSignal" Content="Invoke Chatter Method"  Click="btnShowSignal_Click"></Button>
            <TextBlock Name="txtblock_message" Text="{Binding UpdateText}"></TextBlock>
        </StackPanel>
    </ScrollViewer>
</Window>

Codebehind side
On the codebehind side in the MainWindow.xaml.vb we will create a property named UpdateText which will be set everytime our client receives a new text.  In the XAML side, we bind our TextBlock to this UpdateText property so whenever this property is changed it will be shown in the UI.  For all this to happen we have to implement INotifyPropertyChanged Interface. 

--------------------------------------
Imports Microsoft.AspNet.SignalR.Client
Imports System.ComponentModel
Imports Microsoft.AspNet.SignalR.Client.Hubs

Partial Public Class MainWindow
    Inherits Window
    Implements INotifyPropertyChanged
    Public connection As HubConnection = New HubConnection("http://localhost:8080")
    Public myHub As IHubProxy = connection.CreateHubProxy("myHub")

    Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        DataContext = Me
        connection = New HubConnection("http://localhost:8080")

        myHub = connection.CreateHubProxy("myHub")
        myHub.On(Of String)("addMessage", AddressOf addMessage)
    End Sub

    Async Sub btnShowSignal_Click(sender As Object, e As RoutedEventArgs)
        Await connection.Start()
        Await myHub.Invoke("Chatter", "Hello Server")
    End Sub

    Private m_updatetext As String
    Public Property UpdateText() As String
        Get
            Return m_updatetext
        End Get
        Set(ByVal value As String)
            m_updatetext = value
            RaisePropertyChanged("UpdateText")
        End Set
    End Property

    Private Sub addMessage(ByVal sValue As String)
        UpdateText += Environment.NewLine
        UpdateText += sValue
    End Sub
    Private Sub RaisePropertyChanged(prop As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(prop))
    End Sub
    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
End Class
-----------------------------------------------
Let’s run both of our applications side by side. First Run the Host application and then run the WPF application and put them side by side.  In the screenshot below I have SignalR Owin Host Console Application on the left and WPF application on the right hand side.  Click on the button Invoke Chatter Method which will invoke the server’s Chatter method. 


 As soon as you click on the button it passes the value “Hello Server” to the server and server sends that value back to all the connected clients.  If you want to give it a try then fire up all the SignalR Client Console application too and press any key on the server console window.


After you press any key on the Host application it will send values to two clients as shown below.


And you might be tempted to ask me what about a web application which is the most used application by all of us right. 

SignalR Client Hub Web App consuming Owin Host
Let’s create an empty web application and install Nuget packages as shown below.

>Install-Package Jquery
>Install-Package Microsoft.AspNet.SignalR.JS

Create a simple html page, I have named it as SignalRClientNoProxy.html. You can run the application now to see the output.
-------------------------------------------------
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="Scripts/jquery-2.0.0.min.js"></script>
    <script src="Scripts/jquery.signalR-1.0.1.min.js"></script>    
    <script src="/signalr/hubs" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            var connection = $.hubConnection('http://localhost:8080');

            connection.start();
            var myHub = connection.createHubProxy("myHub");

            $("#broadcast").click(function () {
                myHub.invoke('chatter', $("#msg").val());
            });

            myHub.on('addMessage',function (message) {
                $("#message").append('<li>' + message + '</li>');
            });
        });
    </script>
</head>
<body>
    <div>
        <input id="msg" type="text"/>
        <input type="button" id="broadcast" value="broadcast" />
        <ul id="message">

        </ul>
    </div>
</body>
</html>
------------------------------------------
As a pre-requisite to running our client application on the right we run our server application on the left.


Type something in the textbox on the right window and post something to the server. 


Lets’ run all the applications so far and see how this works.  So one Host and three clients right.

Let now move on to some real world application like Windows Service Application running SignalR Owin Host sending messages to all clients.

SignalR Server Windows Services Application
Now porting this SignalR Owin Host code to window service is easy. Here is the code to do a simple service with signalR. You can check out the code to do a simple windows service from the All-In-One code framework from micrsoft.
------------------------------------------------------
Imports System.Threading
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Hubs
Imports Microsoft.Owin.Hosting
Imports Owin

Public Class Service1
    Private stopping As Boolean
    Private stoppedEvent As ManualResetEvent
    'global variable context to update clients from everywhere in the service.
    Dim context As IHubContext = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
    Dim url As String = "http://localhost:8080"
    Public Sub New()
        InitializeComponent()

        Me.stopping = False
        Me.stoppedEvent = New ManualResetEvent(False)
    End Sub

    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Log a service start message to the Application log.
        Me.EventLog1.WriteEntry("Service is in OnStart.")
        Dim url As String = "http://localhost:8080/"
        Using WebApplication.Start(Of Startup)(url)
            
        End Using
        ' Queue the main service function for execution in a worker thread.
        ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ServiceWorkerThread))
    End Sub


    ''' <summary>
    ''' The method performs the main function of the service. It runs on a 
    ''' thread pool worker thread.
    ''' </summary>
    ''' <param name="state"></param>
    Private Sub ServiceWorkerThread(ByVal state As Object)
        ' Periodically check if the service is stopping.
        Do While Not Me.stopping
            ' Perform main service function here...
            Dim context As IHubContext = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
            For x As Integer = 0 To 100
                System.Threading.Thread.Sleep(3000)
                context.Clients.All.addMessage(x.ToString())
            Next
            Thread.Sleep(2000)  ' Simulate some lengthy operations.
        Loop

        ' Signal the stopped event.
        Me.stoppedEvent.Set()
    End Sub

    Protected Overrides Sub OnStop()
        ' Log a service stop message to the Application log.
        Me.EventLog1.WriteEntry("Service is in OnStop.")

        ' Indicate that the service is stopping and wait for the finish of 
        ' the main service function (ServiceWorkerThread).
        Me.stopping = True
        Me.stoppedEvent.WaitOne()
    End Sub
End Class
Public Class Startup
    Public Sub Configuration(ByVal app As IAppBuilder)
        Dim config = New HubConfiguration With {.EnableCrossDomain = True}
        app.MapHubs(config)
    End Sub
End Class
<HubName("myHub")> _
Public Class MyHub
    Inherits Hub
    Public Sub Chatter(param As String)
        Console.WriteLine(param)
        Clients.All.addMessage(param)
    End Sub
End Class
----------------------------------------
You won’t be able to just hit F5 with a windows service, first you will have to install the windows service then you can run your WPF application and then you could see real time output from the windows service.  As I said before the entire source code for all these apps is on my GitHub page.