Uses for Silverlight reflection, pt. II

So, as promised, here is the followup to what I was doing with Silverlight reflection that made me need access to Internal members of a class.

Localization in Silverlight is still an interesting story and everybody seems to have their own way of doing it. The client I’m on uses Excel spreadsheets that load into a database. The localization data then pulls when a usercontrol loads and changes the controls data based on the locale and what was in the database.

This was very tedious for developers to setup. You would create your UI and then have to go back and pull the default text for your controls and add them all to the spreadsheet.

Using reflection I can create an instance of all the user controls in my assembly and display them to the user in a listbox. From there, when they select a user control, I can reflect on that type and display all the controls defined in the UserControl to the user. When you define a control in xaml and give it a name, it becomes an internal member of a partial class generated by Visual Studio.

So, what I do is when you are all done with your UserControl you simply run my tool on the assembly and it reflects through and shows all the UserControls. When you select one, it uses reflection to create an instance with the default constructor, which initializes all your controls properties.

From there I grab all the controls through reflection and use some logic to get which properties of each I want to localize. For TextBlocks I grab the Text property, for ContentControls it’s the Content property, and so on.

Using that I generate a simple tab-delimited string with all the default localization for all the controls and the user can copy/paste right into Excel and move on to their next task and let someone else do the translating/localizing for them.

Silverlight Reflection and internal members

If you want to use reflection in Silverlight you have to come to grips with the fact that you can only reflect on public members of the class.  This is a very important part of the security features in Silverlight.

However, I have a scenario that would be greatly helped by being able to reflect on internal members.  The documentation I found on MSDN said that as long as the member was visible at compile time you could reflect on it.  This should include internal members in the same assembly or an assembly that’s the target of InternalsVisibleTo.

I was having problems, at first I just tried setting the InternalsVisibleTo attribute in the AssemblyInfo.cs for my project to the project that had my reflection code. 

No such luck, even though I could access the members through normal means.  What I was missing was setting the BindingFlags attribute while calling GetMembers on my type. 

If you pass in BindingFlag.NonPublic | BindingFlags.Public | BindingFlags.Instance it should all work for you now.

Up next will be a post sometime about why I wanted this ability.

Cradling Device Emulator on Windows 7 in VS 2008

I’ve been doing some Windows Mobile work again and keep getting an issue with the Windows Mobile Device Center and my emulator.  Sometimes when I cradle the emulator it works just fine, other times it doesn’t pick up the connection. 

It seemed rebooting fixd the problem, but I’m not gonna reboot everytime I cradle and un-cradle.

So I found another solution that seems to work, when you cradle and nothing happens, uncradle the device again and open up Windows Mobile Device Center, formerly ActiveSync on XP.

Under Connection Settings, click the checkbox to disable DMA connections.  Then hit ok.  Once that is set, reopen the settings and re-enable DMA connections.  Once the settings are applied you can go into the Device Emulator Manager and cradle the device again, it should work now!

Overlaying Controls in WPF with Adorners

One of the common things that comes up on multiple projects using WPF is the ability to overlay the screen or a certain portion of it. Either to create a richer modal-type experience than a message box provides or to block access to a certain portion of the screen while an asynchronous or long running operation is happening.

There are a number of ways to do this but the one I’ve settled on after tackling it on a few projects is an adorner that automatically overlays and control with any content you want.

Other options include using the Popup control, which is problematic because popups are not part of the normal visual layout. They are always on top of all other content and don’t move when you resize or move the window, at least not automatically. Another way you can do it is put everything inside a grid, and add the content you want to overlay with at the end of the Grid’s content with no Row or Column specification. You can set the visibility to collapsed and show or hide based on databinding or triggers, etc. This works better than the popup for resizing, but is not as reusable. Even though the adorner is a bit more code, I think it’s more reusable and better than the Popup option.

The way I use it is I create a UserControl that will be my overlay, let’s call it ProgressMessage. I’ve got a Grid I want to overlay called LayoutRoot. I can then call OverlayAdorner<ProgressMessage>.Overlay(LayoutRoot). Now my grid will be overlaid with the ProgressMessage user control. I’ve also provided an override of the Overlay method so you can actually pass in an instance of the content you want to overlay with.

I use a factory pattern and how IDisposable/using statements work to automatically create/remove the adorner. You could also store the IDisposable that’s returned and call Dispose later to remove the AdornerLayer

using (OverlayAdorner<ProgressMessage>.Overlay(LayoutRoot)) 
{ 
   // do some stuff here while overlaid 
}

A couple of quick notes, because of the way WPF layout and hit-testing works, you should not have any height or width set on your overlay content, and the background needs to be non-transparent. To get a semi-transparent background use the alpha-portion of the aRGB color format on your background. So instead of Black, use #44000000 and that gives you a semi-transparent gray background. Additionally, all these methods block mouse input, but the keyboard navigation remains active. I’ve started playing with lost focus events and other methods to intercept losing focus and retain that. Otherwise the user can tab through the controls underneath the overlay and activate them using arrow keys, enter and space bar. You can either solve this, or once I straighten it out I’ll post what I come up with

 

Here is the rest of the class, OverlayAdorner.cs

    /// <summary> 
    /// Overlays a control with the specified content 
    /// </summary> 
    /// <typeparam name="TOverlay">The type of content to create the overlay from</typeparam> 
    public class OverlayAdorner<TOverlay> : Adorner, IDisposable where TOverlay : UIElement, new()
    {
        private UIElement _adorningElement; private AdornerLayer _layer; /// <summary> /// Overlay the specified element /// </summary> /// <param name="elementToAdorn">The element to overlay</param> /// <returns></returns> public static IDisposable Overlay(UIElement elementToAdorn) { return Overlay(elementToAdorn, new TOverlay()); } 
        /// <summary> 
        /// Overlays the element with the specified instance of TOverlay 
        /// </summary> 
        /// <param name="elementToAdorn">Element to overlay</param> 
        /// <param name="adorningElement">The content of the overlay</param> 
        /// <returns></returns> 
        public static IDisposable Overlay(UIElement elementToAdorn, TOverlay adorningElement)
        {
            var adorner = new OverlayAdorner<TOverlay>(elementToAdorn, adorningElement);
            adorner._layer = AdornerLayer.GetAdornerLayer(elementToAdorn);
            adorner._layer.Add(adorner);
            return adorner as IDisposable;
        }

        private OverlayAdorner(UIElement elementToAdorn, UIElement adorningElement)
            : base(elementToAdorn)
        {
            this._adorningElement = adorningElement;
            if (adorningElement != null)
            {
                AddVisualChild(adorningElement);
            }
            Focusable = true;
        }

        protected override int VisualChildrenCount
        {
            get { return _adorningElement == null ? 0 : 1; }
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            if (_adorningElement != null)
            {
                Point adorningPoint = new Point(0, 0);
                _adorningElement.Arrange(new Rect(adorningPoint, this.AdornedElement.DesiredSize));
            }
            return finalSize;
        }

        protected override Visual GetVisualChild(int index)
        {
            if (index == 0 && _adorningElement != null)
            {
                return _adorningElement;
            }
            return base.GetVisualChild(index);
        }
        public void Dispose()
        {
            _layer.Remove(this);
        }
    }

Back in Business

So, it’s been a few months. Been very busy, got married, closing on a house in November.  Started a new project at work, for the government.  Despite my repeated requests I have yet to receive a dark pair of sunglasses and handgun.  I thought that they were standard issue for the project, oh well, I guess not.

I’ve got some things I’d like to share, so expect more updates starting again soon.  Continue doing a lot of WPF and related work.  It’s great fun and soon I hope to forget entirely what WinForms even looked like. :)

Transactions inside stored procedures

More a short rant today than anything else.  If you are writing a DAL most of it can be generated and be completely boilerplate.  Everything looks the same, acts the same, is called the same way.very beautiful.

There’s always exceptions, however.  Sometimes you just NEED to do something more complicated.  Inserting into multiple tables at once, possibly across different databases.

The project I’m working on has a very consistent way of putting database operations in transactions.  I’ve been troubleshooting a number of problems in the app where the app will crash after trying to save some records.  The proc seemed to be working, it was returning a new id and everything was happy.  Why couldn’t the app find these records?

Because the stored procedures fall under the exceptions to the rule above and the developer of them thought it would be best to do transaction handling inside the stored procedure. 

Two problems, one the transactions across the linked server didn’t work because of configuration issues.  Secondly, the stored proc did a try . catch . rollback without calling RAISERROR.

I certainly think that transactions inside the stored procedure can clean up some of the client code, and help in situations when the stored procedure can be called in many different places and always needs to be transactional.  Just keep in mind that unless we let the calling client know something went wrong it’s just as bad as swallowing exceptions in C# or VB.  Fail fast and hard, as always.

Frame-based animation in WPF

I recently was working on the ubiquitous photo/slideshow app in WPF.  This is something I’ve been tinkering with off and on for last 6 months.  The original intention was to create a photo slideshow application for my upcoming wedding.  Being the nerd, a static video slideshow just wasn’t going to cut it.

Along the way I learned quite a bit about keeping performance up and memory usage low while working with tons of images.  It’s finally in a position where it’s almost done and I wanted to add a few tweaks.  The photos zoom in and randomly arrange like they were dropped on a table.  Once there, they show one by one. 

I wanted to add a little random “drift” while the image was showing to make it more interesting to the eye.  I started originally by creating random storyboards and listening to the Storyboard.Completed event.  When the event fired I created a new storyboard to animate my photo’s Canvas.Left and Top properties.  This worked, but there was an annoying lag between the stop and start of the animations. 

I wanted to move to a frame-based animation rather than WPF’s built-in time-based animation style.  I could have used a timer to update my properties, but I wanted to work more within the constraints of WPF.  I found articles for Silverlight that indicate an empty storyboard with no duration will fire it’s completed event on the next frame, there you can update your properties and restart the storyboard to update your properties every frame.  Although this may work in Silverlight, I could not get it to work in WPF.  Though as I look back, I didn’t try setting the Duration to “0:0:0″.  I wonder if that would work?

Regardless, the technique I ended up using was listening to CompositionTarget.Rendering event it code-behind.  The event fires before your UI renders each frame, allowing you to hook in and do frame based animation.

For more information, you can go here:

http://msdn.microsoft.com/en-us/library/ms748838.aspx

WPF ListBox Virtualization

Virtualization in WPF is amazing when you get it, annoying when you lose it.  I’m working on a form where the user can dynamically filter and sort a ListBox.  I’m using a DataTemplate to give a nice card-like view to each object, which makes it take up a  lot of space on the screen.  To fix this I used the WrapPanel as the ListBox’s ItemsPanel.

 

WrapPanel is not virtualized, I can’t find one that is and don’t have any time to write one myself.  So I came up with a work around to give the user a fixed number of column view using the standard panel for a ListBox.  This got me virtualization back.  Then I wanted to smoothly scroll so I turned ScrollViewer.CanContentScroll to false.  Smooth scrolling, no virtualization.  Because this box may have thousands of records in it, performance is much more important than smooth scrolling. 

The moral of the story is, if you’re working on something in WPF and performance is important and you might have a large dataset coming in.  Double check your changes to controls to make sure you’re maintaining virtualization.  If anybody has a good list of what disables virtualization (grouping, custom panels, smooth scrolling), I’d like to see it.

So long Linux, remember the good times…

Last night I was fighting with repairing my MythTV box, the final remaining linux PC in my house.  My video card went down and trying to replacing it the nVidia that was in there with the ATI replacement I picked up turned out to be too frustrating.  Steps I went through

  1. Backup/Restore of KnoppMyth
  2. #2 caused a bad xorg.conf to be used, and install crashed
  3. Un-tarred the backup, replaced bad xorg.conf with a failsafe xorg.conf, re-tarred
  4. Repeat #2
  5. Video card works, KnoppMyth installation crashes
  6. Powered through, MythTV up and running, can’t talk to backend
  7. Reconfigure backend, can see recordings, can’t watch them
  8. Networking doesn’t work
  9. TV-Out doesn’t work
  10. Give Up
  11. Try to pull recordings onto portable hard drive (NTFS formatted, ha, good try)
  12. Download Knoppix w/ NTFS write support
  13. Run LiveCD
  14. Copy files to portable hard drive

Remaining steps

  1. Wipe linux
  2. Install Windows
  3. Install GB-PVR

Before I started working at Magenic none of my computers booted into Windows by default.  My laptop ran VectorLinux (based off Slackware) and my main PC ran Fedora, Ubuntu, etc based on what I wanted to try that week.

The MythTV box was running rock-solid for years, and I loved it.  It was the last bastion of my free-spirited geekiness in my increasingly Microsoft focused world.  Now, it has but hours left to live.  Maybe I’ll put Ubuntu on my laptop for old time’s sake at some point.  Who knows?

Speaking of, Windows 7 RC is out now to MSDN.  THAT is going on my laptop immediately tonight.  I think I’ve been fully assimilated.  Even Winston eventually saw the light and learned to love Big Brother. 

Hosting WPF in WinForms

I’ve done a lot of WPF and Silverlight, but always as standalone apps. In one project, we actually embedded Silverlight inside a WPF application using a browser control.

I’ve been firmly convinced that XAML is the way of the future for some time now. But recently I’ve gotten to see a very real, tangible benefit of hosting WPF inside a windows form application.

A lot of time businesses will want some fancy visualization or way to view their data. In Windows Forms if you want anything “cool” out of the box you’ve got one of these options: paying for a 3rd party set of controls, finding a half-baked control online at CodePlex or CodeProject, or writing it yourself.

Most of the time the project budget and plan don’t include time or money for options 1 and 3. Option 2 is Russian roulette. Sometimes you get some really cool stuff, sometimes the control you find is garbage. In WPF, it becomes almost trivial to do the sort of complex control customization that was such a pain in WinForms. At the same time, most business probably don’t want to start off by rewriting their existing app in WPF.

Using the ElementHost control and some custom WPF UserControls you can embed some very cool UI functionality with minimal effort and impact to your existing application. My WPF UserControls don’t look like “WPF”. At least not all the LOB demos you see where there are fancy transitions and gradients slapped in everywhere. But it’s blowing away the end users. The integration is seamless, it looks like WinForms, but simply using some stylish DataTemplates and the WPF TreeView we’ve improved the customers user experience ten-fold. We’re using it 3 critical places of the app where the user needed some better visualization of the data that was coming in. With WPF we could do that much faster and better with minimal impact to the rest of the application.