Luke’s Guide to the ListBox Control

Tuesday, January 26, 2010 / Posted by Luke Puplett / comments (0)

This post is a copy (I'd cry if it got mauled) of the Community Content I added to the ListBox MSDN article explaining its highly complex model.

Every time I go to sleep I forget this, may I say, overly complicated beast of a control. Here's some community content that might help programmers of a similar disposition.

Right, a ListBox is a bunch of behaviours over the top of an ItemsControl which is essentially a controller for items in a Panel.

It's useful to consider its template which consists of a Border, a ScrollViewer (of which the ScrollViewer has a ScrollContentPresenter) and an ItemsPresenter.

This Panel can be changed via ItemsControl.ItemsPanel but could also be specified in the control template by adding your chosen Panel and setting its IsItemsHost=true which will hook it up to the ItemsControl/ListBox.

The ItemsControl's job is to generate the items according to customizable templates using an ItemContainerGenerator. For a ListBox, this makes ListBoxItem instances which are ContentControls and thus have ContentPresenters in their templates. Their look is affected using...

ItemTemplate. Simple except that it should not be used in conjunction with ItemTemplateSelector (which sets a DataTemplateSelector class that returns a DataTemplate when its SelectTemplate method is call and so you can add some kind of logic to determine which one to return).

And we're not done yet because there's also ItemContainerStyle and ItemContainerStyleSelector which do a similar job except that they style the container (ListBoxItem) around the item's actual rendered content (as defined by ItemTemplate).

As for the look of the highlight, I guess that's done as part of the template applied to the item in reaction to ListBoxItem.IsSelected. Probably.

[sigh] Whatever happened to HTML and CSS eh?

Labels: ,

Blend 3.0 and VS 2010 :-(

Saturday, January 23, 2010 / Posted by Luke Puplett / comments (1)

This post was written while I was discovering issues with Blend and VS 2010 Beta 2 and publiched in a rush (I’m on my way out but I want to get this out there). Look see, I haven’t even got the time to correct published.

I’ve hastily posted this from a draft I was working on in Windows Live Writer (loving this app aside from the BR tags google seems to add) because I publicly moaned on Twitter about the fact that Blend and now VS 2010 had gotten slow under the weight of WPF – I ordered a 512Mb DDR3 video card yesterday to try and help it - and a guy named Noah Richards purportedly from the IDE Editor Team in Redmond had his bionic Twitter ears on and heard my wimpering. So I thought I’d publish the raw notes I’d been making for him to read…

lukepuplett

MS built VS2010 on super h/w so its slow for me. I must order a super card to run VS2010. Then I can make s/w my customers think is slow.

noahsmark

@lukepuplett My 1GB/single core VMs beg to differ – there are some people with beefy machines, but most are used for server08r2 + hyper-V.

Blend 3.0

Still no right click copy in code editor.

Isolating controls to work on them is improved.

I think about it all too much instead of getting on and using it.

Don’t trust it not to screw my XAML up. Everything I do, I do tentatively, holding my breath waiting for it to explode. And this is learnt behaviour, for it crashes with such regularity.

I found the sample data feature and read about it but within 20 clicks of using it I had broken it.

InvalidCastException: Unable to cast object of type ‘_SampleData.v7.GuideSearchResultsSampleDataItemCollection’ to type ‘System.Windows.Data.CollectionView’

Of course, the problem is that I don’t care for why this happened or to find out. I just want it to work and when it doesn’t, to tell me why or to prevent me making the action in the first place. And besides, I don’t know how to troubleshoot this because its not my code that’s throwing, its Blend’s magic sample data design-time wiring.

Isn’t Blend aimed at creative people or do modern designers have to learn type theory??

WPF is powerful because it leverages the .NET Framework. But Blend doesn’t work well enough to completely insulate the user from having to know and think in .NET.

Our creative brain is on the right but our logical brain is on the left. As an artist I learned that we work our best when one or the other is dominating the processing.

This page http://www.viewzone.com/bicam.html features a nice table of the left and right brain functions.

Blend doesn’t let my right brain dominate for long enough for me to flow.

Traditionally web development uses a lot of sliced imagery. This is because drawing applications are typically reliable and easy to use and allow the designer to roam freely around her creative mind, playing. Then they cut the image up and sew it onto an HTML chassis and let a programmer merge it with some stuff from a database.

Because its unenjoyable I wonder if it means designers may not refine apps as they find it too painful and think “That’ll do”. The World could end up with slightly worse software because the tools are painful. It’s like how the mobile internet only took off when Apple made the tool enjoyable (iPhone).

In fact, if I’d started this project with XAML and its toolset, I’d have thrown in the towel within weeks. Maybe I’m not cut from UI devigner’s cloth.

As for my problem with the sample data, I won’t use that ever again. I’ll go back to my way of doing it which was to design the component in another project and then cut and paste the XAML over.

Visual Studio 2010 Beta 2

Same problem as in VS 2010 with right-clicking highlighted text removes highlight while context menu is open.

And VS 2010 editing is now painfully slow. This doesn’t surprise me as a WPF programmer because Windows Presentation Foundation is big.

I’m sure I’m not alone in that my first thoughts with WPF were that such an enormously complicated object model must come at a price. Layers of objects with so many members and events flying both up and down a deep visual tree.

Toolbar customization is a backward step. I cannot assign icons or edit tool buttons in place.

Collapsible region highlighting distracts me and the +/- buttons aren’t perfectly lined up, making them take a nanosecond longer to use. Pasting collapsed methods, opens them.

Scrolling doesn’t feel as fast. Parts of the screen don’t draw properly, sometimes the whole VS real-estate flickers on and off and I see my desktop for a brief moment.

Switching between code editor/designer tabs takes ~1 second :(

Mostly its not terrible but the difference that I feel the most is in the text editor, and of course that’s where I spend most of my time. The IntelliSense is a bit slower and it just tips it over to the wrong side of satisfactory.

The hourglass fails to appear in many situations leaving me trying to click things and hovering over buttons to see if the window has frozen.

Some resources failed to resolve, leaving the designer to miss rendering parts of my view. An error in the Error List indicated that an xmlns reference could not be resolved. I removed the reference below:

xmlns:SampleData="clr-namespace:Expression.Blend.SampleData.GuideSearchResultsSampleDataSource"


And then I replaced the reference because I wanted to look further into the issue resolving that Expression reference but undoing my changes led to the issue being resolved. I reloaded the designer for my view and that too all worked, presumably because the resources had now built.



Incidentally, copying and pasting the text above from App.xaml to this blog entry resulted in the App.cs file unexpectedly opening – since uninstalling “Copy from Visual Studio for Windows Live Writer” this seems to have stopped happening.



Loading multiple-projects seems to be a bit faster and they’re sorted A-Z now. Builds seem a bit quicker, particularly if its dependencies were only just built.



And generally it is a nicer place to be that 2008. Visual Studio has been a wonderful piece of software since 2005 and wasn’t ever bad at all. I often wonder if I could ever get on using another major technology stack because I’d miss VS too much.



Remember I’ve posted this without checking it or removing google’s BRs. Here goes nothing.

Flowing Custom Control Values to ViewModel/Bindings

Friday, January 15, 2010 / Posted by Luke Puplett / comments (0)

This article discusses an issue I had when making a custom login box control, particularly the issue of getting the values in the username and password boxes to flow back down to the view-model. The issue might be my design, which could be fundamentally wrong, if only I knew of another way to do it.

The problem with Windows Presentation Foundation and its more promiscuous sister, Silverlight, is that its as good as it is bad. That is, its hard to deny its brilliance when you're carving out complex drawings and alpha gradients, adding subtleties to button animations and then there's the whole hardware accelerated 3D bit. But its bloody complicated because its mandate is to be everything to everyone and when so much is done for you all that stuff has to be massively multifaceted.

My LoginControl uses the parts and states model and the WPFToolkit to get at the VisualStateManager. I won't go into these things as they're documented enough and Karen Corby has a great MIX session video on it, too.

So I have a few parts, two TextBox controls and a Button. You can guess that these are username, password and the logon button.

Firstly, and I'll get this one over and done with quickly: I don't use the PasswordBox control. It does not support data binding because it takes a cautious approach and does things securely. Instead I apply a strikethrough formatting to a regular TextBox within its default style in generic.xaml.

You can see how this is done by reading my comments at the bottom of the MSDN article on the PasswordBox.

Welcome to my LoginControl

Cutting straight to the meat of the implementation, my control has the following properties:

  • private TextBox UsernameTextBox // the property which stores the TextBox UI control part/element for the username
  • private TextBox PasswordTextBox // the property which stores the TextBox UI control part/element for the password
  • public string Username // the dependency property which stores the username that can be bound to from a view model
  • public string Password // ditto but for the password

Because I can't bind my view model to a property of a the LoginControl's username TextBox and I don't want to expose the TextBox controls publicly, I use the following trick to hook up a binding between the TextBox.Text dependency property and LoginControl.Username (ditto for the password):

private TextBox UsernameTextBox
{
    get
    {
        return (TextBox)GetValue(UsernameTextBoxProperty);
    }
    set
    {
        // Detach observer from outgoing value.
        //
        var oldValue = this.UsernameTextBox;
        if (oldValue != null)
        {
            BindingOperations.ClearAllBindings(oldValue);
            oldValue.GotKeyboardFocus -= new KeyboardFocusChangedEventHandler(TextBoxes_GotKeyboardFocus);
            oldValue.KeyUp -= new KeyEventHandler(Username_KeyUp);
        }

        SetValue(UsernameTextBoxProperty, value);

        if (value != null)
        {
            value.SetBinding(TextBox.TextProperty, new Binding("Username")
            {
                Source = this,
                Mode = BindingMode.TwoWay
            });
            value.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(TextBoxes_GotKeyboardFocus);
            value.KeyUp += new KeyEventHandler(Username_KeyUp);
        }
    }
}

And once that's done there's nothing else to consider except that when adding my LoginControl to my XAML page, I need to hook up the binding to the appropriate properties in the view model. That's easy:

Username="{Binding Path=Username, Mode=TwoWay}" Password="{Binding Path=Password, Mode=TwoWay}"

No worries there.

In Practice it Fails

The problem occurs when the login button is clicked and the ICommand is executed. The RelayCommand on the view model kicks in and my Action runs but if I stop the debugger right there I see that my view model does not have up-to-date Username and Password values!

My theory is that the binding system has not done its magic in between my typing of text and clicking of button. And although in theory the LostFocus events upon which data binding updates rely should have been triggered, my daisy-chained setup is somehow ballsing things up. Actually, there is a LostFocus on the username TextBox which should update the LoginControl.Username property, it doesn't, but even if it had, what's the activator to get the value to then jump from the Username property to its source down in my view model? By the way, flows up from source seem to work fine.

Whatever, I don't know. My solution was to grab each of my bindings and manually hit the UpdateSource method from within the login button's click method:

private void LoginButtonElement_Click(object sender, RoutedEventArgs e)
{
    var utbx = this.UsernameTextBox.GetBindingExpression(TextBox.TextProperty);
    utbx.UpdateSource();

    var ptbx = this.PasswordTextBox.GetBindingExpression(TextBox.TextProperty);
    ptbx.UpdateSource();

    var ubx = BindingOperations.GetBindingExpression(this, UsernameProperty);
    var pbx = BindingOperations.GetBindingExpression(this, PasswordProperty);

    ubx.UpdateSource();
    pbx.UpdateSource();

    if (this.PasswordTextBox != null)
    {
        if (!this.PasswordTextBox.IsFocused)
        {
            this.PasswordTextBox.Focus();
            if (!this.TryLoginButton.IsMouseOver)
                return;
        }
    }

    if (this.Command != null)
        this.Command.Execute(new KeyValuePair<stringstring>(this.Username, this.Password));
}

Which brings me right back to the point I made earlier about not doing this the right way. I'm not sure any other way would flow the values in time anyway. But then there's always the question of how everyone else doesn't seem to have this problem...

Labels: , , ,

Note to self: Turning a Path into a Resource in XAML

Wednesday, January 13, 2010 / Posted by Luke Puplett / comments (0)

Simple post mainly as a reminder to myself explaining how to make a complex path reusable because I keep forgetting this easy thing.

This goes in the asset resource dictionary.

<PathGeometry x:Key="ArrowHeadPath" Figures="M140.00002,39.999641 C134.47716,39.999641 129.47714,42.23822 125.85786,45.857513 L124.94602,46.962662 51.908844,119.99984 124.94678,193.03778 125.85786,194.14201 C129.47714,197.76131 134.47716,199.99988 140.00002,199.99988 151.04572,199.99988 160.00005,191.04556 160.00005,179.99985 160.00005,174.47699 157.76146,169.47699 154.14217,165.8577 L153.43225,165.27196 153.55394,165.14679 108.407,119.99986 154.20343,74.203423 154.14198,74.141975 154.14217,74.14183 C157.76146,70.522537 160.00005,65.52253 160.00005,59.999672 160.00005,48.95396 151.04572,39.999641 140.00002,39.999641 z M120,0.5 C185.99803,0.5 239.5,54.001972 239.5,120 239.5,185.99803 185.99803,239.5 120,239.5 54.001972,239.5 0.5,185.99803 0.5,120 0.5,54.001972 54.001972,0.5 120,0.5 z" />

Then this is how to use it (StaticResource probably better, transforms just for demo):

<Path Data="{DynamicResource ArrowHeadPath}" RenderTransformOrigin="0.7,0.5" MouseLeftButtonDown="ActivateWindowDrag" >
<Path.Fill>
<RadialGradientBrush GradientOrigin="0.495,0.55">
<GradientStop Color="#FFE2E2E2" Offset="0"/>
<GradientStop Color="#CC0F0316" Offset="0.3"/>
</RadialGradientBrush>
</Path.Fill>
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="3.6" ScaleY="3.6"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="8"/>
<TranslateTransform X="5" Y="-160"/>
</TransformGroup>
</Path.RenderTransform>
</Path>

Labels: ,

How I Dynamically Load a ViewModel from the Web

Tuesday, January 12, 2010 / Posted by Luke Puplett / comments (0)

For my vuPlan client I wanted to avoid those 'update me' messages that Adobe products are good at annoying me with. My aim was to be able to tweak my application logic, perhaps fix bugs, and do it unobtrusively. I also wanted to maintain a typical execution context of an ordinary locally installed application. To be clear, I've not fully investigated the options open to me with ClickOnce, and recently I became a user of Seesmic Desktop which is the first time I've seen it used in the wild. But even if you have different design goals, here's how I do dynamic MVVM.

This article is not a complete code breakdown of the method, rather a 10,000ft overview with a few details. The concept is straight-forward enough for most OO programmers to get.

Overview

Dunno about you but I'm a visual learner and find graphics and diagrams more palatable than words alone. This schematic should compress most of what would otherwise be a long and arduous blog post into 1080x673 (if you look at the full size one I stuck on flickaarrrr).

Diagram of ViewModel class relationships

Each of the black-rimmed screen looking objects are ViewModel classes. The inheritence tree runs right to left and so rooted with ViewModel.cs.

This class is the base for all and every view model I use thoughtout my application and is very similar to the base VM Josh Smith defines in his excellent MSDN article on the Model-View-ViewModel pattern.

The only addition to Josh's base ViewModel worth mentioning is that I add a property (typed as object) which I used to store a reference to the Dispatcher for the UI control to which the ViewModel will be bound.

The coloured blocks define the code distribution in the sense of partitioning over assemblies. (A) is the actual WPF application executable/project and would reside on the client PC once deployed, (B) is the dynamically loaded assembly containing business logic and (C) is a reusable shared library.

The assemblies reference each other like so:

  • Assembly A references
    • The shared library C
  • Assembly B references
    • The shared library C
  • Assembly C references
    • Nothing other than the usual

The Shared Client .dll (C)

Two classes are defined in here. The abstract base ViewModel, as mentioned above, and an abstract base MainViewModel class. This latter class defines all the properties that the WPF view will bind to, but contains no other logic.

It also defines the ICommand properties into which behaviour and logic will be placed. This is an example of an ICommand to hook up to a Login button (in MainViewModel.cs):

public ICommand LoginCommand
{
    get
    {
        if (_loginCommand == null)
        {
            _loginCommand = new RelayCommand(param => this.Login(param), param => this.CanLogin(param));
            //_loginCommand = new RelayCommand(param => this.Login(param));
        }
        return _loginCommand;
    }
}
RelayCommand _loginCommand;
protected virtual void Login(object obj) { throw new NotImplementedException(); }
protected virtual bool CanLogin(object obj) { throw new NotImplementedException(); }

The RelayCommand comes straight from Josh Smith's article mentioned above. The key to it are the two virtual methods which will be overridden in the implementation assembly.

N.B. It may be possible to skip this class as I think WPF bindings are loosely coupled and not checked at build time. The XAML for my view simply contains lines like {Binding Path=Username} (for the username textbox) and so it stands to reason that any object instance could be set as the DataContext and binding/reflection will just work where it works and fail where it fails - although don't quote me on that.

I also define delegates for some actions such as closing the window or application which allows me to shift the implementation of that logic to where I know how I want it to work (in the application UI itself).

The Implementation Logic .dll (B)

I call this class MainImplViewModel and it contains an InitializeComponent method which in many ways is the main initializer for the application - remember that the UI assembly (A) is supposed to be 'dumb'.

For my app, it assigns some delegates and default property values. It also does things like checking if the internet is connected and altering property values which can affect whether various UI controls are active as well as loading stuff in from IsolatedStorage.

As mentioned above, I have a reference to the Dispatcher for the UI and so I also define utility methods for marshalling work onto that thread and my application also has a synchronisation process, so there's a private BackgroundWorker variable and event handlers there, too.

And of course, I override the methods that my RelayCommand objects rely on (in MainImplViewModel):

protected override bool CanLogin(object obj) { ... }
protected override void Login(object obj) { ... }

Within which is the actual implementation which can trigger UI changes by modifying the properties, starting my BackgroundWorker and all manner of stuff.

The Application UI XAML .exe

The job of the pared-down application code is to i) check we're online or that the local cache is available (Isolated Storage), ii) download the implementation assembly (B) from a URL and iii) load it.

Once loaded, the types defined in the implementation assembly are scanned and the first class of type MainViewModel that is found is instantiated and assigned to a local variable within the application as well as the DataContext of the main window.

I have written a pretty complex background component loader/initializer class but the main thrust of what its doing is simple; download the file from a website using an ordinary http get, then load the assembly from the raw bytes with Assembly.Load(bytes).

After this is done, it fires an event which continues the ViewModel load process and is handled like so (in app.xaml.cs):

void Initializer_AfterComponentLoaded(object sender, TypeLoadEventArgs e)
{
    if (e.Instance.GetType() == typeof(ResourceDictionary))
    {
        Application.Current.Resources = (ResourceDictionary)e.Instance;

        this.MainWindow = (Window)LoadComponent(new Uri(@"MainWindow.xaml", UriKind.Relative));
        this.MainWindow.Show();
    }
    else if (e.Instance.GetType() == typeof(System.Reflection.Assembly))
    {                
        UI.MainViewModel mainVm;
        if (this.Initializer.AssemblyLoader.TryLoadType<UI.MainViewModel>(out mainVm))
        {
            this.MainWindowViewModel = mainVm;
            this.MainWindow.DataContext = mainVm; // DataContext set to view model.
            
            mainVm.ShutdownApplicationAction = new Action<int>(ShutdownVuplan);
            mainVm.ScrollIntoViewAction = new Action(delegate
            {
                //var listBox = ((Window1)this.MainWindow).MainListBox;
                //if (listBox.Items.Count > 0)
                //    listBox.ScrollIntoView(listBox.Items.GetItemAt(listBox.Items.Count - 1));
            });
            mainVm.Dispatcher = this.MainWindow.Dispatcher;
            mainVm.ParentControl = this.MainWindow;

            this.SessionEnding += new SessionEndingCancelEventHandler(App_SessionEnding);

            mainVm.SyncStatusMessages.Add(Client.UI.StringHelper.TryGetWinFxResourceString("Status_Message_Initializing"));
            mainVm.InitializeComponent(this.CloudStatus); // Warning: Go To Definition will jump to base impl.
        }
        else
        {
            if (this.Initializer.AssemblyLoader.TypeLoadException != null)
                throw this.Initializer.AssemblyLoader.TypeLoadException;
        }
    }
}

I like to leave all my code around so you can get an idea of the other stuff I do. For example, my loader also loads a resource dictionary from the web, based on location – this is a subject for a different blog post, but you can see that I roll my own localization this way. The method above checks what type of object was loaded and if its an Assembly (the implementation assembly) it hooks it up.

What’s most important here is that I set MainWindowViewModel to point to the view model and then set the DataContext of my main window. Further down, I call the all important InitializeComponent and so any state changes to the view model made during this method will be reflected in the view.

To load a type from the implementation assembly I use a generic method TryLoadType<T>

public bool TryLoadType<T>(out T instance) where T : class
{
    this.TypeLoadException = null;
    instance = null;
    try
    {
        if (this.Assembly == null)
            throw new InvalidOperationException(UI.StringHelper.TryGetResourceString("ErrorMessages", "ErrorVitalReferenceIsNull"));

        foreach (Type t in this.Assembly.GetTypes()) // Exceptions here probably due to assembly dependencies of wrong version (remote assembly not latest build).
        {
            if (typeof(T).IsAssignableFrom(t))
            {
                instance = (T)this.Assembly.CreateInstance(t.FullName);
                // this.OnLoaded(new TypeLoadEventArgs(instance));}
            }
        }
    }
    catch (Exception e)
    {
        // Could throw any of 6 exceptions.
        //
        this.TypeLoadException = e;
    }
    return (instance != null);
}

The important bit here is the foreach loop that looks for the type specified in T. MainImplViewModel is derived from MainViewModel so the calling code only need know of the MainViewModel type and it will load the class with all the implementation logic.

The caller (in this case, the method above this one) can also set properties on the view model because it knows of the base type – this is why I have a MainViewModel (recall that I mentioned that in theory it could be excluded).

Conclusion

I've not the time to simplify my example code above, I've just ripped out lumps of code from my projects, thus making it more complicated and excluding things that may have made it more readable, sorry, but I think the general idea can be grasped by most programmers au fait with MVVM.

Using this technique, I can keep my business logic in an implementation assembly, fix bugs in it, and then publish the .dll file to a web server and my clients will be updated invisibly.

Which reminds me: remember to add an XCOPY command to the post build actions for the implementation DLL which copies the assembly to your web server. Easily forgotton - you'll wonder why your breakpoints aren't being hit.

Labels: , ,

Debugging an Assembly Load (Reflection or not)

Friday, January 01, 2010 / Posted by Luke Puplett / comments (0)

The Visual Studio Solution I have been using for a while has grown to 11 projects. It's also dependant on a bunch of libraries from a resuable framework I've been working on which I intend to use across various products. Since working in XAML, I broke off the client components to lighten the burden on the IDE. Problems arose after I made some major changes to my resuable framework.

The framework I have is an evolving beast that I call Steelcore. My vuPlan projects use various libraries from this framework by referencing the release built DLLs.

Since VS 2010 is around the corner and has a slew of thread debugging features, and due to an issue with the way I added tracing instrumentation to my code, I cut out a few classes related to thread tracking and even entire namespaces and re-versioned to 2.0.0.0.

This is not an issue for my unfinished vuPlan project as I own the source and I can just right-click each reference under each vuPlan component, check its property sheet states 2.0.0.0 and rebuild the lot. Nothing else to worry about right?

Right. All was fine when building, sure, but when working in my light-weight solution (just has the WPF client bits) and I tried to run it.

Could not load file or assembly 'Steelcore.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abcdef0123456789' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

An interesting point about the way I've written the vuPlan client is that it has only the skinniest of clients, just UI, and the implementation logic is downloaded from the web at startup, loaded with reflection and plugged-in to the UI using polymorphic viewmodels. One day I shall blog about that. But the reflection part of the scenario is a red-herring and I troubleshot the problem as if it were an ordinary 'early bound' load error.

The exception was being thrown by a class that downloads the implementation assembly and enumerates the types within. Just the enumeration caused it to blow up. Needless to say, I rebuilt and ensured my implementation assembly was up-to-date and that the locally cached copy was, too.

Troubleshooting Method

My first mode of attack was to double-check all references within all projects, in all solutions including the Steelcore library itself, just in case one component was using an old version or using a version that was using an old version.

I also made a decision to increment the minor version number of all vuPlan assemblies to reflect their dependence on the radically different Steelcore DLLs. This would prove useful later.

My second was to fire up I'll Dazzle 'em (ILDASM.exe) and take a peek at the manifest. This was a good move because within the list of references was this intriguing bunch of text:


.assembly extern Steelcore.Data as Steelcore.Data_13
{
.publickeytoken = (80 72 6D A9 F7 97 F6 5E ) // .rm....^
.ver 1:0:0:0
}

Must admit it might have said "as Data_13" I'm not sure because my machine crashed on resume from sleep just before typing this and I lost the original paste.

Anyway, there were TWO references to Steelcore.Data.dll and the one above looks like some auto-gen alias to help it reference an old version probably by proxy, i.e. probably because some other reference references it.

So my final tool was Fuslogvw.exe which is the Fusion log viewer/manager. Fusion is the name for the bit of the .NET Framework that goes looking for referenced assemblies and so this would prove most useful indeed. This was Suzanne Cook’s baby when she blogged and her articles haven’t lost any of their usefulness.

Fuslogvw.exe

The interesting section is obviously the blue section. Here we see that two S26.Vuplan.Core libraries are being loaded, each of differing versions, and that dastardly Steelcore.Data 1.0.0.0.

Each item in the log opens an HTML doc which shows further information.

Captured Fusion Log Entry

And as expected, the "Calling assembly" line shows that it is the old version of Vuplan.Core that's causing my grief.

Solution

Despite having thought I'd checked each of the assemblies, I'd clearly missed one. Aware that an old copy of the core lib was being referenced, I suspected and double-checked the client components again and found the bad reference.

I twigged that when I'd broken off those projects a few weeks ago, I must have reset the references to the built DLLs although I still find it unusual that it didn't just pick up the new version and work - my references to Steelcore did! Maybe it was pointed at a different path or something.

Blames His Tools

What would have helped was if Visual Studio had a different colored icon for project references and static file references.

It'd also be nice to see the version number next to each reference.

Labels:

ActiveSync Encountered a Problem on the Desktop

Tuesday, December 29, 2009 / Posted by Luke Puplett / comments (0)

This is just a quick note explaining a method I used to resolve the error message above.

Firstly, I disconnected the phone and closed Outlook and repaired all my storage files using the old ScanPst.exe tool that's secreted away when Outlook is installed.

C:\Program Files\Microsoft Office\Office12\SCANPST.EXE

I pointed this at my primary storage file, which is an Offline Store because I used the Windows Live Connector to get at my Hotmail account.

C:\Users\lukepup\AppData\Local\Microsoft\Outlook\lukepup_hotmail.ost

And then I repaired all other PST files I use, just for completeness. During the repair, ScanPst can hang and be reported as Not Responding - this is surely because while its single thread does the repair it stop pumping the window message queue.

Then I deleted the partnership in Windows and also on ActiveSync actually on the phone itself; run ActiveSync and then in Options, hit Delete on the head of the tree of folders which kills the partnership and cleans up.

I opened Outlook on the desktop and let it do it's thing with Windows Live. It seemed to detect major changes because it appeared to exhaustively sync every item in all folders, taking 10 minutes.

Closed Outlook when done and connected the phone. Setup a new partnership with different names in case it linked back to old registry data. Allowed a good 10 minutes to complete. Well, actually it never completes because I've had a problem for months where it encounters some kind of error and restarts, but this doesn't happened until all items are in, so I don't really worry about it.

Disconnected, done.

Labels: ,