Mark Gilbert's Blog

Science and technology, served light and fluffy.

WPF Media Player – Alternate Features

Getting the WPF Media Player to version 0.1 wasn’t all smooth sailing.  In fact the norm was rocky shoals, rocky shoals, The Flying Dutchman attacking, fog, more rocky shoals, and THEN a clear channel.


One of the rocky shoals I hit was with the SlideUpAnimation that I talked about previously.  Here is the definition that I eventually went with:

SlideUpAnimation = New Animation.ThicknessAnimation(New Thickness(e.JewelCaseBottomLeftCorner.X, e.JewelCaseBottomLeftCorner.Y – 20, 0, 0), _

     New Thickness(e.JewelCaseBottomLeftCorner.X, e.JewelCaseBottomLeftCorner.Y + 5, 0, 0), _

     New Duration(New TimeSpan(0, 0, 0, 0, 200)))

As I mentioned before, the ThicknessAnimation constructor takes three parameters – the beginning Thickness, the target Thickness, and the Duration in which to adjust the Margin from the former to the latter.  However, my original attempt at getting this to work was the following:

SlideUpAnimation = New Animation.ThicknessAnimation(New Thickness(e.JewelCaseBottomLeftCorner.X, e.JewelCaseBottomLeftCorner.Y + 5, 0, 0), _

     New Duration(New TimeSpan(0, 0, 0, 0, 200)))

I was using a different constructor for ThicknessAnimation here, one that only requires the target Thickness and the Duration.  In all of the other animations defined up to this point, I didn’t need to specify the starting point because I wanted the new animation to start working on the object from wherever it was already.  I thought I would following the same steps here.

What I didn’t take into account on this particular animation is that the JewelCaseExpand control would be capable of moving around the screen, and more so than simply the sliding effect that I was trying to implement.  The JewelCaseExpand control is tied to the location of the JewelCase on the shelf.

So, when I implemented the version without specifying starting location, I found the JewelCaseExpand control actually following my mouse horizontally.  The best effect was when I moused over a JewelCase on the far left of the Shelf, moused away, and then (without touching any JewelCase in between) moused over a JewelCase on the right right.  The JewelCaseExpand control would appear on the left, and go zooming over to the right, and slide down at the same time.

Basically, because I hadn’t changed where the JewelCaseExpand control was left when it was hidden and hadn’t specified the starting point explicitly, the rendering engine remembered where it was and used that as my starting point.  This is a cool feature, but not what I wanted.


One of the patches of fog that I encountered was with how I programmatically attached the JewelCaseExpand control to the main form.  As I’ve mentioned previously, there is at most one instance of this control attached to the form.  Most of the form uses the CurrentJewelCaseExpand property to access it, and that property takes care of instantiating it and hooking it up.

Private ReadOnly Property CurrentJewelCaseExpand() As JewelCaseExpand
        Dim AlreadyExists As Boolean

        AlreadyExists = Not IsNothing(Me._CurrentJewelCaseExpand)
        If (Not AlreadyExists) Then
            Me._CurrentJewelCaseExpand = New JewelCaseExpand()
            Me._CurrentJewelCaseExpand.Name = “MyJewelCaseExpand”

            ‘ For fun, comment the first and uncomment the second.  Then try mousing over an album.
            Me.RegisterName(Me._CurrentJewelCaseExpand.Name, Me._CurrentJewelCaseExpand)
            ‘Me.RegisterName(Me._CurrentJewelCaseExpand.Name, Me.MainGrid)
       End If

       Return Me._CurrentJewelCaseExpand
    End Get
End Property

Originally, if the object didn’t already exist, I would instantiate it, give it a name, and add it to the Main form’s Children collection.  Apparently that wasn’t enough because I got the following error: “ ‘MyJewelCaseExpand’ name cannot be found in the name scope of ‘WPFMediaPlayer.Main’ ”.  I did some digging, and came across the topic of NameScopes.

Based on the error message, and the articles I was finding online, I pieced together that you have to formally register the name of the control so that the rendering engine will recognize it.  When you create a control in XAML, this is done implicitly, but because I am defining the control in code, I have to do it explicitly.

Conveniently, the System.Windows.Window class provides a method called “RegisterName” (huh, go figure) to do just this.  The method takes two parameters – the name that you’re trying to register, and the scoped element that you’re registering it to.  My first thought was that the “scoped element” was the Grid .  I added the control to the Children collection of the grid, so I should register the name of that control with the grid, right?

Wrong.  I’ve left my original call in the code for your amusement.  Swapping out these two calls to RegisterName gets past the exception, but it was most assuredly NOT the effect I was going for.  As near as I can tell, when you register the name with the Grid, and not the JewelCaseExpand control itself, the grid becomes the target of the animations that we’ve defined for the JewelCaseExpand control.  Here is what the grid looks like with this change, but before I’ve moused over any of the JewelCases on the Shelf:


And here is after touching the first JewelCase:

First Touch

And the second:

Second Touch

And the third:

Third Touch

You get the idea.  This might be a useful feature in some cases, but not here.  I am still working to get my head wrapped around the concept of NameScopes, so the use of RegisterName is still something of an exercise in code roulette.


There you have it.  A couple of interesting features that might be useful in some applications.



March 11, 2008 - Posted by | WPF/Silverlight

Sorry, the comment form is closed at this time.

%d bloggers like this: