Tag Archives: wpf

Hosting Winforms in Firefox

Standard

 image

I have a strange fascination with hybrids.  Combining old and new technologies in bizarre and interesting ways.   Why must developers make “the choice” between a web or native technology? It would be great to build applications that would increase or decrease in features depending on the platform they were run on.

 

clip_image002

Do you have a Winforms application that you’d like to host in a web browser?  There’s an interesting technique you can use to do this enabled by .net Framework 3.5.

The .net framework provides the ability to create WPF web applications (commonly called XBAP).  WPF has the ability, in turn, to host Winforms. 

Security

It appears that in order to do this effectively, it’s necessary to deploy your XBAP application as a “Full Trust” application.

image

The code

To use this, create an XBAP project, then a page a “WinformHost” control on it.   The XAML could look like this:

<Page x:Class="Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Page1">
    <DockPanel LastChildFill="True">
        <Button Name="Button1"  DockPanel.Dock="Bottom"  >This is a WPF Button</Button>
        <WindowsFormsHost Name="WinformHost"   />
    </DockPanel>
</Page>

Then, create some code to instantiate your winform and show it on the Winform host:

Class Page1

    Private Sub Page1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim loForm As New HelloWorldWinform

        WinformHost.Child = WinformToUserControl.GetWrapper(loForm)
        loForm.Show()

    End Sub
End Class

Here’s the subroutine:

Public NotInheritable Class WinformToUserControl

    Public Shared Function GetWrapper(ByVal form As System.Windows.Forms.Form) As System.Windows.Forms.Control
        Dim loPanel As New System.Windows.Forms.Panel
        loPanel.Dock = Forms.DockStyle.Fill
        ShowFormInControl(loPanel, form)
        Return loPanel
    End Function

    Private Shared Sub ShowFormInControl(ByVal ctl As System.Windows.Forms.Control, ByVal frm As System.Windows.Forms.Form)

        frm.TopLevel = False
        frm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None
        frm.AutoScaleMode = Forms.AutoScaleMode.Dpi
        ctl.Controls.Add(frm)

        frm.Dock = Forms.DockStyle.Fill

    End Sub
End Class

   

Interesting bits and pieces

We found that in order for the items inside the control to scale properly, the AutoScaleMode property on the Winform must be set to Dpi instead of the default, which is Font.  I have a feeling this is because Dpi is the mode preferred for WPF, but I am uncertain.

In the sample WinformToUserControl class I found it better to contain the Winform inside a panel rather than exposing the Winform directly.  It seemed to make it more stable.  Feel free to experiment with taking it off.

Gotchas

As of time of writing, Firefox on my Windows 7 64 bit machine steadfastly refuses to run xbap.  It appears the “Windows Presentation Foundation” addin has not been automatically installed.  I have no idea how to install it.  There’ appears to be no information about how to do so.  So if you have it, good for you.  If you don’t….try re-installing the .net framework 3.51 (which didn’t work for me…)

I do know there was some controversy about this addin being temporarily blacklisted by Mozilla due to security concerns last month, but that’s all over now isn’t it?  

 

Download

You can download a sample project here.

image

Links

Advertisements

Silverlight 3 style NavigationContext in WPF

Standard

 image

At the moment I’m experimenting with various user interface technologies.  Because the prototypes are working in parallel, I want to reuse code where possible.  With this in mind, I’ve created a couple of useful wrapper functions for navigation in both Silveright 3 and WPF that I thought I’d share.

 

In case you don’t know the Silverlight 3 Beta now has a navigation framework that works in a similar way to WPF’s Frame navigation feature.   To learn more about it, check our Jeff Poise’s great article Silverlight 3’s New Navigation Framework.

 

I brief, to navigate to a new page and pass a parameters you use a syntax like this in the code behind:

 

Me.NavigationService.Navigate(New Uri(String.Format(“/SomePage.xaml?someparameter={0}”,somevalue), UriKind.Relative))

 

In the loaded event of the page you’re navigating to, you use code like this:

 

Private Sub MyPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
     txtSomeTextbox.Text =  Me.NavigationContext.QueryString("someparameter")
End Sub

 

Nicer Navigating

I found the Navigate method above a little awkward, so in Silverlight I created a little helper function called “NavigateTo”, on page that makes the code a bit nicer.

 

Me.NavigateTo(“/SomePage.xaml”,”someparameter”,somevalue)

 

Here’s the implementation:

 

Imports System.ComponentModel
Public Module PageHelper
    <System.Runtime.CompilerServices.Extension()> _
   Public Sub NavigateTo(ByVal page As System.Windows.Controls.Page, ByVal navigationUrl As String, ByVal ParamArray arguments() As String)
        Dim lsUrl As String = navigationUrl & "?"
        Dim lbIsParamName As Boolean = True
        For Each lsArg As String In arguments
            lsUrl &= lsArg
            If lbIsParamName Then lsUrl &= "="
            lbIsParamName = Not lbIsParamName
        Next

        page.NavigationService.Navigate(New Uri(lsUrl, UriKind.Relative))
    End Sub

End Module

 

Nicer NavigationContext

 

I found Silverlight3’s NavigationContext quite nice to use.  Unfortunately this is not available in WPF.  I set about creating a helper function that would emulate this functionality in WPF.

 

WPF Navigation Helper

 

Here’s a WPF version of PageHelper that allows a compatible syntax with Silverlight3.  

 

Imports System.ComponentModel
Public Module PageHelper

    Private WithEvents moCurrentNav As NavigationService
    <System.Runtime.CompilerServices.Extension()> _
   Public Sub NavigateTo(ByVal page As System.Windows.Controls.Page, ByVal navigationUrl As String, ByVal ParamArray arguments() As String)

        '  Update Navigation Args
        Dim loNavigationUri As New NavigationContext

  If arguments.Length > 0 Then
            For i As Integer = 0 To arguments.Length - 1 Step 2
                 loNavigationUri.QueryString.Add(arguments(i), arguments(i + 1))
            Next

            End If

           
        loNavigationUri.Uri = New Uri(navigationUrl, UriKind.Relative)

        ' Strip the Xaml extension 
        Dim lsClassName As String = navigationUrl.Substring(0, navigationUrl.Length - 5) 
        ' Make my class name 
         Dim lsName As String = page.GetType.Namespace & "." & lsClassName 
        ' Instantiate the class 
        Dim loPage As Page = page.GetType.Assembly.CreateInstance(lsName) 
        ' Do the Navigation 
         page.NavigationService.Navigate(loPage, loNavigationUri)
    

        ' Store the current NavigationService so we can complete
        moCurrentNav = page.NavigationService

    End Sub
    <System.Runtime.CompilerServices.Extension()> _
Public Function NavigationContext(ByVal page As System.Windows.Controls.Page) As NavigationContext
        Return moLastNavContext
    End Function
    Private Sub moCurrentNav_Navigated(ByVal sender As Object, ByVal e As System.Windows.Navigation.NavigationEventArgs) Handles moCurrentNav.Navigated
        moLastNavContext = e.ExtraData
        moCurrentNav = Nothing
    End Sub
    Private moLastNavContext As New NavigationContext

End Module
Public Class NavigationContext
    Public QueryString As New Dictionary(Of String, String)
    Public Uri As Uri
End Class

 

I also have provided primitive support for cross-assembly navigation.

 

I hope someone found this useful, let me know.

 

 

Share this post :

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

WPF and the Supervising Controller/Presenter Pattern

Standard

image

I’ve previously stated that the MVP pattern could be advantages for XAML based applications.  I haven’t provided WPF examples yet as I fear that these may compromise the design-ability of the XAML layout.  

Florian Krusch describes the beginnings of an MVP style pattern for WPF (and Silverlight) applications in his article:

WPF – DM-V-VM or M-V-P – WTF?

He states that the pattern described by Martin Fowler  “Supervising Controller Pattern” (still under development at time of writing) may be relevant in this case.  (The term Controller and Presenter are used interchangeably in Fowler’s article)

This pattern has been created in order to facilitate frameworks such as WPF that have a data binding capability.   I understand however that it expects one-way data binding (read) with the view look at the model directly.  Updates to fields are delegated to the controller, which in turn updates the model.  This sortve neuters the 2-way data binding in WPF.

The true objective of these architectures is testability, with the assumption of the view being difficult to work with in the unit test environment.

An architecture that may work is something like the diagram below:

 

image 

In this proposal both the View and Model could be mocked successfully.

In future posts I’ll endeavour to  create some code to show how this may work in the real world.

Share this post :

Weird Science – Defining Winforms in XAML

Standard

image

I like to think of XAML as an “object instantiation script”.  According the to the main books on the subject it should be possible to utilise XAML to create any kind of .net object. 

Practical examples include WWF (Windows Workflow Foundation) , which allows the storage of definition in XAML, which is nothing to do WPF.  WPF (Windows Presentation Foundation) was the original reason XAML was created, but XAML was designed to be independent.

So I was thinking, why not see if I can define a traditional “Winform” in XAML.    Why would I want to?   I thought it might be fun.   As it turns out, it may actually be useful in some scenarios.  (With a great stretch of the imagination)

So does it work?  Oh yes it works and it works well.   “Well” means that VS2008 provides full intellisense for tags within the Xaml designer, as well as “code behind”.  Now that, my friends, is cool.  Imagine being able to create form layouts using XML tags instead of that oh-so-last year winforms designer!  The result is surprisingly WPF like, which I find intriguing.

To create the example below, I created a WPF project, then removed the default WPF “Window1.xaml” and replaced it with my own “Form1.xaml”:

<Form Name="Form1" x:Class="Form1"  Text="Hello" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
        >
    <Form.Controls>
        <FlowLayoutPanel>
            <FlowLayoutPanel.Controls>
                <TextBox Name="txtName" x:Name="txtName" />
                <Button Name="cmdSayHello" Text="Say Hello" Click="Button_Click" /> 
            </FlowLayoutPanel.Controls>
        </FlowLayoutPanel>
    </Form.Controls>
</Form>

Please note that features such as code behind (partial classes), event hooks and most things in the “x” namespace work fine.

Creating XAML from an existing Winform

For even more fun and games, you can feed a running instance of a Winform into XAML Writer and get XAML source.  Sadly winforms incorporates read-only properties, so without massaging the Xml you’re not going to be able to clone a Winform using XAML serialization just yet.

The code would look something like this:

Dim loWinform As Form = Me ' Some Winform
Dim lsWinformXaml As String = XamlWriter.Save(loWinForm)
Dim loClonedForm As Form = XamlReader.Load(new XmlTextReader(new StringReader(xaml)))

 

See this Mike Hillberg’s object cloning article for more information.

 

So where from here?

What’s the use of it?  Well for me it proved that Xaml can be used to create any sort of object graph.  

Possible uses for this:

  • Embedding Winforms instantiation code within a WPF XAML document (something I haven’t tried)
  • Streaming Winforms form definitions from a server down to a client (effectively allowing a WebServer to render Winforms just like it renders HTML pages)
  • Providing a good interim step in creating a Winforms to WPF Converter

 

Any Comments?

If you find this topic interesting, ask questions or download a sample project, write some comments on the blog.  If I can see interest in the topic I may develop it further.

Share this post :

kick it on DotNetKicks.com