Fun with ILDASM and ILASM: tweaking the code of an existing library

Today I decided it was the appropriate time to upgrade my work PC from Windows 7 to Windows 8. I’m already using Windows 8 on my personal PC as well as on my //BUILD/ Slate. Re-installing an OS is never really exciting but this time I faced an interesting challenge… In this short blog post I share this story !

Check-list

The PC I’m using at work is a HP Elitebook8560P laptop. I had no doubt Windows8 would work like a charm on it, so I started by writing up the list of major tools I need:

  • VS2005 (yes, the 2005 version – that’s a long story… it’s for C++ work)
  • VS2010 + SP1
  • Office 2010
  • Office 2013

I also would like to install VS2012 but one of the .Net component I’m using in the large WPF app I’m currently working on has a bug with .Net 4.5. If I install VS2012 .Net4.5 will be installed to and prevent the execution of my app. This was at least the behavior I found out on Windows7 while taking a look at VS12.

The team in charge of the component (which are co-workers btw) are aware of the issue and already fixed it. We didn’t integrate their last version yet however.

Installation

This is the part you press and button, grab a cup of cofee and get back in front of the screen to press another button. Nothing really interesting here…

Fun-time

Ok, everything is installed. Time to check I can run my app. Arrrrg !!! Crash !!!

I took me a few seconds to figure out that Windows8 comes with .Net 4.5 pre-installed. Well, that’s a problem, at least for me. I reviewed the option I had:

  • go back to Windows 7 and reinstall everything again. I didn’t have the time for that.
  • remove .Net 4.5 from my laptop. This is actually not possible since .Net 4.5 comes with Windows8.
  • come at work very early monday morning and try to grab the new version of the buggy component. This is a very bad option since I’m in the middle of an important delivery…
Then I realize I knew exactly what was going wrong in the component that lead to the crash. What about disassembling the code to IL (Intermediate Language), recompile it and use this hacked DLL ? This is what I did, and it worked very well 😀

Why a crash ?

Just to share the context, the buggy component is a WPF control. It contains UI virtualization stuff. One of the method contains a “throw NotImplementedException”. This method is called when a particular Dispose() method is called. This method was NEVER called prior to .Net 4.5 hiding the problem. The new version of the .Net framework calls the Dispose method properly… and then throws the exception 🙂

Introducing ILDASM and its friend ILASM

ILDASM is the MSIL disassembler provider with Visual Studio. It comes with a very basic UI but you can also use it a command line and dump the content of a .Net binary to a file (containing the IL). So I fired up the VS2010 command prompt and typed:

ildasm.exe Company.BuggyComponent.dll /output Company.BuggyComponent.il

I then opened the file using a basic text editor, navigate to the method which contains this code:

.method public hidebysig newslot virtual final 
 instance void Clear() cil managed
{
 // Code size 6 (0x6)
 .maxstack 8
 IL_0000: newobj instance void [mscorlib]System.NotSupportedException::.ctor()
 IL_0005: throw
} // end of method VirtualizingCollectionSelector`1::Clear

I changed it to:

.method public hidebysig newslot virtual final
 instance void Clear() cil managed
{
 // Code size 1 (0x1)
 .maxstack 8
 IL_0000: ret
} // end of method VirtualizingCollectionSelector`1::Clear

Then I rebuilt a new DLL using ILASM. The tool is able to create an executable or an assembly from IL code in a text fix. So I simply typed:

ilasm Company.BuggyComponent.il /key=company.snk /output=CompanyBuggyComponent.dll

I dropped the newly created assembly in the bin directory, and boom, it’s working again. Of course this is a temporary solution but I had fun coming to it 🙂

PS: the 3 screens running Windows8 at home: personal workstation, slate and work laptop

Animating item selection in a WP7 application

Another day another occasion to share an implementation detail behind my 2Day todo-list application. In this post I share the code used to animate the selection in a ListBox. Here is what is looks like in the create/edit folder dialog of 2Day:

[mediaplayer src=’/wp-content/uploads/2012/09/Listbox-animation.mp4′ ]

You can grab the source code directly here if you want.

Background

The basic idea is to create another element behind the ListBox which will be animated when the selection changes. The tricky part is to find out the appropriate coordinates of this element to make sure it’s perfectly on top of the element we need to higlight.

XAML

The XAML is not very complicated. Notice I use a particular style on the ListBox to remove its scrolling capability. I have to do that because otherwise if the user perform a drag gesture on the ListBox, it moves its element without moving the overlay I need to add. I use a simple Grid to be able to add the overlay “behind” the ListBox:


    



    
        
    

    
        
            
                
            
        
        
            
                
                    
                
            
        
    

Code

The code is for now in the code-behind of the view (see next paragraph for improvements ideas). I use the ItemContainerGenerator property of the ListBox to retrieve the UI element from the Data element (in this example: an integer).

Then I use the TransformToVisual method to get the location of the visual relative to the parent ListBox. Next step is to animate the position of the item using DoubleAnimations:

public partial class MainPage : PhoneApplicationPage
{
    private readonly Point emptyPoint = new Point();
    private DoubleAnimation animationX;
    private DoubleAnimation animationY;
    private Storyboard storyboard;

    public MainPage()
    {
        InitializeComponent();

        this.listbox.ItemsSource = Enumerable.Range(1, 32);

        this.Loaded += this.OnLoaded;
    }

    private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        this.Loaded -= this.OnLoaded;

        this.listbox.SelectionChanged += this.OnSelectionChanged;

        this.overlayHost.Height = this.listbox.ActualHeight;
        this.overlayHost.Width = this.listbox.ActualWidth;
        this.overlayHost.Margin = this.listbox.Margin;

        this.UpdateHighlightedItem();
    }

    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        this.UpdateHighlightedItem();
    }

    private void UpdateHighlightedItem()
    {
        var element = this.listbox.ItemContainerGenerator.ContainerFromIndex(this.listbox.SelectedIndex) as FrameworkElement;
        if (element != null)
        {
            // compute the location of the selected element
            Point destination = element.TransformToVisual(this.listbox).Transform(this.emptyPoint);
            Point origin = this.iconOverlay.TransformToVisual(this.listbox).Transform(this.emptyPoint);

            var translateTransform = this.iconOverlay.RenderTransform as TranslateTransform;
            if (translateTransform == null)
            {
                translateTransform = new TranslateTransform();
                this.iconOverlay.RenderTransform = translateTransform;

                TimeSpan duration = TimeSpan.FromMilliseconds(150);
                IEasingFunction ease = new QuarticEase { EasingMode = EasingMode.EaseOut };

                this.animationX = new DoubleAnimation { Duration = duration, EasingFunction = ease };
                this.animationY = new DoubleAnimation { Duration = duration, EasingFunction = ease };

                this.storyboard = new Storyboard();
                this.storyboard.Children.Add(this.animationX);
                this.storyboard.Children.Add(this.animationY);
            }
            else
            {
                this.storyboard.Stop();
            }

            Storyboard.SetTarget(this.animationX, translateTransform);
            Storyboard.SetTarget(this.animationY, translateTransform);
            Storyboard.SetTargetProperty(this.animationX, new PropertyPath(TranslateTransform.XProperty));
            Storyboard.SetTargetProperty(this.animationY, new PropertyPath(TranslateTransform.YProperty));

            this.animationX.From = origin.X;
            this.animationY.From = origin.Y;
            this.animationX.To = destination.X;
            this.animationY.To = destination.Y;

            this.storyboard.Begin();
        }
    }
}

Possible improvements

As you have seen, the current code is not easy to reuse. I think all the logic cold be embedded in a reusable component. Either using an attached property (and tweaking the template of the ListBox) or by subclassing the orginal ListBox class. I leave this exercise to the reader 🙂

Conclusion

In this article I shared the technique used in 2Day to animate the item selection. Many improvements are possible on top of this code, but I hope it could help WP developers.

Download the source code here if you want.

[WP7] Handling events in the items of a ListBox (Windows Developer Show podcast challenge)

Ryan, I you read this, please shout a small advert for my 2Day todo-list application, thanks 😀

Tonight while listening to the Windows Developer Show podcast, a nice challenge came up as a listener had a question about usage of events in a ListBox on the Windows Phone platform. Ryan had the good idea to suggest that a listener could write a blog post before the end of the show to help this guy, and here we are 🙂

Background

In the sample app, because of lack of time, I go straight to the point. In the XAML, I have a ListBox databound to an ObservableCollection. I use code-behind and I’m not using MVVM pattern but for the point of this article, I guess it’s good enough. So here is the XAML:


    
        
            
                
            
        
    

and here is the code-behing:

public partial class MainPage : PhoneApplicationPage
{
    private readonly ObservableCollection dataSource;

    public MainPage()
    {
        this.InitializeComponent();

        this.dataSource = new ObservableCollection { new Item { Name = "Ryan" }, new Item { Name = "Travis" }, new Item { Name = "Jeremy " } };

        // no MVVM for this sample...
        this.DataContext = this;
    }

    public ObservableCollection DataSource
    {
        get { return this.dataSource; }
    }
}

public class Item 
{
    public string Name { get; set; }
}

Wiring events

So now the question is: how I can use events for the items inside the ListBox. Here are the options you have:

Options 1: use event handlers

The idea is just to setup an event handler in the XAML of the DataTemplate. Here is the XAML:


    
        
            
                
            
        
    

and here is the associated C#:

private void Border_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
    // option 1
    // sender is the Border
    // navigate the visual tree up to find the ListBoxItem if needed
    // datacontext is the instance of the Item objects
}

Option 2: use commands

Another option is to use command which is very common for MVVM apps. The trick you might need is to wire an command on something that is not a button. But the problem is that it’s the Button type which has a Command property. A possible trick is to style the button to make it looks like a standard control, here is an example:


    
        
    
                 
    
        
            
                
            
        
    

Option 3: use attached properties

Another option, use attached properties. See this blog post about the way to achieve that. The blog post is old and targets WPF but the same principles are valid for a Windows Phone 7 app.

Option 4: use MVVM Light’s EventToCommand

MVVMLight is a very nice MVVM framework. EventToCommand is an extension of the previously described attached properties and can help you attach a command to an event.

Hope it helps 🙂