Monthly Archives: October 2007

Cross Thread User Interface updating in WPF

Standard

Recently I tried to update a WPF Dependency property from a System.Timer thread and received a “Cross Threading” error.  This wasn’t entirely unexpected, as I’d encountered similar issues in Winforms in the past.

In Winforms, methods such as Invoke, BeginInvoke and InvokeRequired are used in order to force code to run on the UI thread.

The absence of these methods (but not the error message) in WPF was disconcerting.  Fortunately those methods (and many more) do exist, via an extra object called the “Dispatcher” object that hangs off all Ui Elements.  

image

Links

Forum Post – http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=328693&SiteID=1

WPF Threads: Build More Responsive Apps With The Dispatcher — MSDN Magazine, October 2007

Advertisements

Encoded Ampersands (&) and Web Crawlers

Standard

I encountered a problem recently where IBM’s Omnifind Web Search Engine would not crawl internal links rendered within PersPective wiki.

Basically the problem is it could only navigate links like this:

http://someserver/somepage?param1=foo&param2=foo2

As opposed to this:

http://someserver/somepage?param1=foo&param2=foo2

 

The second version complies with XHTML 1.0 recommendations.  PersPective, like many XSLT based web renderers, is unable to render and unencoded ampersand. 

This is not good news.

My solution was to create an ASP.NET based HttpModule which filtered the output to replace the encoded ampersands.

So a  link such as:

<a href=”http://foo/wiki/perspective.aspx?action=view&amp;pagename=system:Welcome”>Click here</a>

Will be changed to:

<a href=”http://foo/wiki/perspective.aspx?action=view&pagename=system:Welcome”>Click here</a>

 

The solution works well.    My code is in VB.NET, although the article I based it on is in CSharp.  Take a look at “Producing Xhtml Compliant Pages With Response Filters” for more information.

 

The project is in Visual Studio 2003 format (.net 1.1) to match the current version of PersPective, although I’m sure it only needs a quick recompile to work with 2.0.

I’ve uploaded a zip file containing the dll and source here.  Enjoy!

PersPective Wiki Turns 3!

Standard

I have posted before about PersPective Wiki, a simple WYSIWYG wiki that to me seems to be one of the best. 

For some time the author Alan Slater has been working on a new version that promises features such as:

  • New look and feel
  • Fully hierarchical structure
  • Advanced editor, with following features:
    • Table editing
    • Paste & Clean content from MS Word
    • Modify text & background colors
    • Spell checker
    • Insertion of wiki links by browsing
    • Image map editing
  • Technical notes:
    • Database backend
    • Built in .Net 2.0
    • XHTML and CSS layout

 

Recently Alan has hosted the a version of the new software on his site  if you’d like to take a quick look.

Today he also made the Alpha available for download. 

Here’s a screenshot of the new editor:

 

image

(Click for more detail)

A way of detecting if an Outlook Contact has been updated since last synced with the server

Standard

This entry concerns a common problem in the world of occasionally connected clients and synchronising changes.  I thought I’d document my solution as it uses less known Outlook attributes.  Those doing similar things might find it useful.   It assumes a knowledge of VSTO, Visual Studio 2005 and VB.NET. 

At the moment I’m working on a process to synchronise Outlook contacts items with contacts stored in a database on the Server.

There’s always a question of which updates take priority (Outlook or Server?), and how to detect if things are updated.

The Rules

I’ve devised a couple of rules that determine which updates are the master:

  • If the Server record has been updated since we last synced, overwrite the local record
  • If the local record has been modified since the last server update, don’t overwrite it

Implementation

When translating a server record to a client contact, I save the following properties to the Outlook Contact:

loNewContact.SetUserProperty("ServerContactId", ServerRecord.Id)
loNewContact.SetUserProperty("ServerTimestamp", ServerRecord.Vers)
loNewContact.SetUserProperty("ServerLastUpdateDateTime", Now.AddSeconds(20))

loNewContact.Save

 

ServerContactId : Associates the client record with the server record

ServerTimestamp: Is the value of a field used on the server to indicate when the server record is updated.  In this case it’s an integer. 

ServerLastUpdateDateTime : This indicates when this record is synced.  It is compared with Outlook’s Local LastModificationTime property in order to determine if the local record has been updated since last sync.  The adding of 20 seconds to the ServerLastUpdate property is because calling “Save” on the contact will update the LastModificationTime property to a later value.

 

The “SetUserProperty” routine is a quick way of setting user properties. ie:  

Public Sub SetUserProperty(ByVal name As String, ByVal value As String)  

       With CType(moOutlookItem.UserProperties, UserProperties)
           Dim loProp As UserProperty = .Find(name)
           If loProp Is Nothing Then
               loProp = .Add(name, OlUserPropertyType.olText)
           End If
           loProp.Value = value
       End With
End Sub

 

The synchronisation logic contains a loop that goes through the server items, checking if they are already local (using the ServerContactId user property.

For items that already exist, I use this piece of code to determine whether to update or not:

 

If mbTheServerRecordHasBeenModifiedSinceLastUpdate(loServerContact, loPimContact) Then

       ' Update the local record
        ....

Else
      ' If the contact has been updated since the last server sync
      If mbThePimContactHasBeenUpdated(loPimContact) Then

                      ' Issue an update request to the server
                    

       End If
End If

 

The routines look like this:

 

Private Function mbTheServerRecordHasBeenModifiedSinceLastUpdate(ByVal serverContact As ContactDetail, ByVal pimContact As IPimContactItem) As Boolean
    Dim lsServerVers As String = pimContact.GetUserProperty("ServerTimestamp")
    If IsNumeric(lsServerVers) Then

        ' If the server has been updated since the last update
        ' of this record
        Return (CInt(lsServerVers) <> serverContact.Vers)

    End If
 
    Return False
End Function

Private Function mbThePimContactHasBeenUpdated(ByVal pimContact As IPimContactItem) As Boolean
    Dim lsLastServerUpdateDateTime As String = pimContact.GetUserProperty("ServerLastUpdateDateTime")
    Dim loPimContactLastModificationDateTime As Date = pimContact.LastModificationDateTime
    If IsDate(lsLastServerUpdateDateTime) Then

        Return CDate(lsLastServerUpdateDateTime) < loPimContactLastModificationDateTime

    End If
 
    Return False
End Function

 

I’m sorry to say I do not have a downloadable code sample you can use, as it tends to be quite specific to the associated server process.    If you have any interest or comments about this code, please post a comment.

Twittering from Outlook Using VBA

Standard

image

Recently I toyed with the idea of letting my boss know what tasks I completed in a day in the hope he actually believes I’m doing something.  I thought of sending constant emails or keeping a diary.    Something briefer was would be more useful.

This got me thinking about services such as Twitter.  Perhaps it has a purpose after all.

I do keep track of tasks in Outlook using the “Getting Things Done” method (I’ll post on this another time) using macros.  I thought I’d see how easy it was to report status updates to twitter.  As it turns out, very easy!

The following simple code sample can be reused to send messages to Twitter:

Sub PromptForTwitterPost()
    Dim lsInput As String
    lsInput = InputBox("Type in text of twitter Post", "Twitter", "")
    If lsInput = "" Then Exit Sub
    PostToTwitter lsInput
End Sub
Sub PostToTwitter(statusUpdate As String)
    PostToTwitterWithAuth statusUpdate, "someuserid", "somepassword"
End Sub
Sub PostToTwitterWithAuth(statusUpdate As String, username As String, password As String)

     Dim WinHttpReq As New WinHttpRequest
     ' Assemble an HTTP Request.
    WinHttpReq.Open "POST", _
      "http://twitter.com/statuses/update.xml?status=" & statusUpdate, False
    WinHttpReq.SetCredentials "yyyyyyyyy", "xxxxxxxxx", HTTPREQUEST_SETCREDENTIALS_FOR_SERVER
    ' Send the HTTP Request.
    WinHttpReq.Send
End Sub

 

This example will work with any Office VBA or VB6 language. 

You can use this macro to use task items to get the status text:

 

Sub ReportTaskAsComplete()

   ' Extract task title
   For Each loItem In Outlook.Application.ActiveExplorer.Selection
    If TypeOf loItem Is TaskItem Then
         Dim loTask As TaskItem
         Set loTask = loItem
         loTask.Status = olTaskComplete
         loTask.Save
  
         PostToTwitter Task.Subject & " - Complete"
    End If
   Next

End Sub

 

Links

  • If you want a deluxe solution for Twittering in Outlook, try Outwit