Tuesday, March 23, 2010

Windows Phone 7 Book

Charles Petzold has written a Windows Phone 7 book and has posted a free preview here: http://charlespetzold.com/phone/index.html

Just thought I’d spread the word. More to come on Windows Phone 7 development. Happy Coding!

Wednesday, March 3, 2010

Creating a Vista "Flip 3D" Menu Using Custom Layout Panels

 

image

Silverlight provides several layout panels which can be used to layout almost any simple user interface. These layout panels are the Grid, Canvas and StackPanel. In more sophisticated user interfaces, however, these basic layout panels may not be enough. In this chapter, you will learn how to create a custom layout panel that organizes its children in a 3D stack. We will create a test application for this panel which will allow you to manipulate various properties of the panel in order to achieve different visual effects including one similar to what is seen in Windows Vista Ultimate “Flip 3D” feature (Alt+Tab while various applications or folders are open to see the “Flip 3D” feature in action) .

To begin, we need to create a new project Silverlight Class Library project in visual studio and name it CustomPanels. Now, add a class to the project and name it Stack3DPanel. Stack3DPanel needs to derive from Panel in order to inherit some of the properties and methods common to all layout panels. The most important of these is the ‘Children’ property which contains all the visual elements to be arranged by the panel. Next, we will add the dependency properties needed to manipulate the way the panel will layout its children.

Define Dependency Properties

Whenever creating properties on custom Silverlight classes, you should consider making those properties dependency properties. Although there are numerous reasons to create them as dependency properties, the most compelling reasons are arguably that dependency properties can support animations, styling and data binding. The dependency properties we will create for the Stack3DPanel are the DepthOffset, HorizontalOffset, VerticalOffset, SkewYAngle and Blur properties.

Before creating the dependency properties, we need to create a static event handler which will execute whenever any of the dependency properties’ values change. Whenever a dependency property value changes, we want to rearrange the children in the panel accordingly. To do so, we simply call the InvalidateArrange method available to us because we derived from the Panel class. Notice we cannot directly access the panel’s InvalidateArrange method by calling this.InvalidateArrange() because this method is a static method. However, the DependencyObject parameter contains a reference to the panel. We can therefore access it as a Stack3DPanel to get to the InvalidateArrange method.

image

The DepthOffset property specifies the depth between items within the panel. This correlates to the projected location of the item relative to the z axis. The greater the DepthOffsett, the greater the distance between objects in the panel. Consequently, the items in the panel will appear to get closer to the user as the DepthOffset increases.

image

Note, the Stack3DPanel arranges its children in a Last In First Out (LIFO) fashion. In other words, the first item inserted into the panel is placed at the bottom of the stack and all successive items will be placed on top of that. To add the DepthOffset property, we need to add a public static dependency property and a public property to access it. This pattern will be repeated for all the dependency properties we will create for this panel.

In order for the Silverlight property system to use the dependency property, we must follow the naming conventions it defines. Dependency properties themselves have unique basic names (DepthOffset). When creating the identifiers for those properties, the basic name is combined with the suffix Property (DepthOffsetProperty). When defining the property’s identifier, we register the dependency property by calling the static Register method of the DependencyProperty class. We will provide 4 parameters for this method. The first is the basic name of the property (i.e. DepthOffset). The second is the data type of that property. The third parameter identifies the type of the class registering the dependency property which in this case is Stack3DPanel. The final parameter is of type PropertyMetaData. This last parameter ultimately identifies what event handler to execute whenever the value of that dependency property changes. In this implementation, we want the same method to be executed whenever any of our dependency properties change, so instead of defining a new PropertyMetaData object within the Register method call (which is typically done), we will define a private variable of type PropertyMetaData which will point to the OnLayoutPropertyChanged event handler.

image

After we have created the property identifier, we can create the property which simply sets/gets the appropriate dependency property value from the Silverlight property system by calling get/set value for the appropriate property identifier.

public double DepthOffset

image

For the following dependency properties, we follow this same pattern; define the identifier by registering and then the property with a getter and setter for which access the registered dependency property.

The HorizontalOffset property specifies the amount of horizontal space between items within the panel.

image

First, we register the dependency property.

image

And then we define the HorizontalOffset property.

image

The VerticalOffset property specifies the amount of vertical space between items within the panel.

image

First, we register the dependency property.

image

And then we define the VerticalOffset property.

image

The SkewYAngle property specifies the angle by which all the items within the panel are skewed along the y axis to create various visual effects.

image

First, we register the dependency property.

image

And then we define the SkewYAngle property.

image

Lastly, Blur property specifies if a blur effect is applied to the items within the panel giving the illusion of loss of focus as the individual items are further away from the user.

image

Firs, we register the dependency property.

image

And then we define the Blur property.

image

Implement Overrides

Now it’s time to work on the heart of the Stack3DPanel. Whenever creating custom layout panels, the two most important methods that you must override are MeasureOverride and ArrangeOverride. We’ll start by implementing the MeasureOverride method.

image

MeasureOverride method first calls the Measure method for each child element. This call is necessary for the child element to calculate its DesiredSize property, which is later used in the ArrangeOverride method. The method then simply returns the availableSize it originally provided.

As its name suggests, the ArrangeOverride method is responsible for placing the children of the panel in their appropriate locations. In essence, this method contains all the logic which causes the panel to arrange its children in a 3D stack formation. While iterating through all its children, the ArrangeOverride method first center aligns each child element both vertically and horizontally. Second, a BlurEffect is applied to the children if the Blur property is set to true and if the current child element is not the first in the list. We do not want the first child element blurred because it appears in front of all the other elements. The appropriate visual effect is for those that are further back to appear blurred while the ones in front appear more focused. Then, the elements are placed on the panel. This is done by calling the child.Arrange method. Initially, all the children are placed in the same location. A series of projections and a transforms are then applied to the children according to their relative position to achieve the appropriate visual effect. First, a SkewTransform is applied with the AngleY set to the value in the SkewYAngle property as a RenderTransform. Finally, a PlaneProjection is applied to each child element. Where LocalOffsetZ, LocalOffsetX and LocalOffset Y are set to i*DepthOffset, i*HorizontalOffset and i*VerticalOffset respectively. At the conclusion of the method, the finalSize value passed in as a parameter is returned. This is typically done in most custom panel implementations. Note: when the panel is rendered, the last child element will appear in the front of the stack (closest to the user) and the first child element will appear in the back (furthest from the user).

image

Define Operations

One feature we will add to this custom panel is the ability to interact with it. We want to allow users to cycle through the items in the stack panel by popping the element on top off the stack and pushing it to the bottom of the stack allowing users to easily flip through the children in the panel. To do this, we must implement the Push, Pop, Cycle and CycleBack methods.

The panel we are creating is called a 3DStackPanel because it lays out its children in a 3 dimensional stack formation. The way we will implement that adding and removing of items from this panel, however, will more closely resemble that of a queue. Because we are calling it a 3DStackPanel, we will use name these operations Push and Pop as is typical of any stack. Note, in a traditional queue implementation, elements are added in the back of the queue and removed from the front. These operations are known as enqueue and dequeue respectively. In essence, we will implement an enqueue method and name it push and a dequeue method and name it pop.

We start with the simplest method to implement – Push. The Push method takes in an UIElement as an input parameter. This is the element that is to be inserted into the stack. We simply insert it in the front of the Children collection. Because of how the ArrangeOverride method was implemented, inserting the element in the front of the Children collection will make it appear in the back of the stack once it is rendered to the screen.

image

The Pop operation will simply remove the last child element (which is rendered at the front of the stack) from the stack and returns it. We need to check for an empty Children collection. If there are no children, the method simply returns null;

image

Now that Push and Pop have been implemented, we can add two other methods that combine these operations to allow us to flip through the stack. The cycle method will take the element appearing in the front and place it in the back. This is done by calling the Pop method and then the Push method with that same element. After we have rearranged the Children collection by calling the Push and Pop methods, we call the InvalidateArrange method to rearrange the elements on the screen.

image

The CycleBack method will do the opposite of the Cycle method. It removes the first element in the Children collection, which appears in the back of the stack, and sets it as the last in the Children collection, which in turn places it in the front of the stack when rendered. Again, once the Children are rearranged, we call InvalidateArrange to arrange the elements on the screen.

image

The last piece of functionality we will add is mousewheel interactivity. We will allow users to cycle back and forth through the elements in the panel by scrolling back and forth on the mouse wheel. To do this, we need to add a MouseWheel event handler. We then simply call the Cycle and CycleBack methods inside the event handler depending on which way the mouse wheel is rolled.

image

We have now finished implementing our custom Stack3DPanel. Now, let’s create a sample application to use this panel to arrange images in the 3D stack.

Create Sample Application

Add a new Silverlight Application project to the Visual Studio Solution and name it PictureStack. This will add two projects to the solution, the silverlight project (PictureStack) and a web project (PictureStack.Web). Paste the following XAML into MainPage.xaml located in the silverlight project to layout the user interface. In this user interface, we are placing an instance of the Stack3DPanel and using data binding to manipulate all the dependency properties we defined for it.

image

image

Now add the following code to MainPage.xaml.cs to implement the application logic. All we are doing is calling the Cycle method when the cycle button is clicked and using an OpenFileDialog to add images to the Stack3DPanel.

image

Now, run the application and experiment by changing the values of the slider to come up with different visual effects. I encourage you to also experiment with this new panel by placing images and other user interface elements such as buttons, textboxes, and other layout panels to create more sophisticated user interfaces. An interesting use of this custom panel would be to use to layout various screens of an application wizard.

Thursday, February 11, 2010

How to properly create image Thumbnails in Silverlight

 

Here is a link to a blog post I found very helpful. It shows how to properly create image thumbnails using the BitmapImage class without running out of memory. I am mainly posting this to keep a reference of it. Check it out. It’s a very common problem. I have run into it multiple times.

http://www.wintellect.com/CS/blogs/jprosise/archive/2009/12/17/silverlight-s-big-image-problem-and-what-you-can-do-about-it.aspx

Silverlight 4 – New Features

 

As a Silverlight developer, I have mixed emotions when I find out there is a new version of Silverlight just around the corner. On one hand, I love playing with the new bits and seeing how the new features will make my life easier, but on the other hand, it also means I have a lot of work to do in order to update my current applications in order to take advantage of some of those new features. Well, Silverlight 4 is just around the corner. I have played around with the bits a little and have read my blog posts and articles on the new features. Some of the more exciting ones are:

String Formatting: This is a small thing, but it saves so much time! By using this new feature, I can get rid of about half of the value converters I am currently using.

Notification API - “Toast” feature seen in Windows.

Hosting HTML content – I haven’t played with this one yet, but this feature will help me get rid of several “hacks” in my code… Overlaying html on a Silverlight application can be a pain… especially if you want that html content to scroll. One MAJOR problem with this feature… it is only supported in out of browser mode. Note to Silverlight Team: “Please make this available in the browser!”

Webcam and microphone support… Yes!

ICommand support in Buttons

ViewBox Control – I use this control a lot in WPF when working with images. It’s great that it’s finally made it to Silverlight.

Printing

Drag-and-Drop Support

Right Click and Mouse Wheel Support

Clipboard Support

Here are just a few links that talk about some of the new sl 4 features.

http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx#webcam

http://wildermuth.com/2010/01/21/New_SL4_Feature_Commanding

http://wildermuth.com/2009/11/27/Silverlight_4_s_Printing_Support

http://wildermuth.com/2009/11/23/Taking_a_WebCam_Photo_with_Silverlight

http://wildermuth.com/2009/11/18/Data_Binding_Changes_in_Silverlight_4

http://timheuer.com/blog/archive/2009/11/22/silverlight-4-notification-window-queue-sample.aspx?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+timheuer+%28Method+%7E+of+%7E+failed+by+Tim+Heuer%29

http://www.wintellect.com/CS/blogs/jprosise/archive/2010/01/09/silverlight-4-s-new-notification-windows.aspx

http://www.wintellect.com/CS/blogs/jprosise/archive/2010/01/04/silverlight-4-s-new-managed-extensibility-framework.aspx

http://www.wintellect.com/CS/blogs/jprosise/archive/2009/12/22/silverlight-4-s-new-html-hosting-support.aspx

http://www.wintellect.com/CS/blogs/jprosise/archive/2009/12/01/silverlight-4-s-new-command-support.aspx

http://www.wintellect.com/CS/blogs/jprosise/archive/2009/11/26/silverlight-4-s-new-drag-and-drop-support.aspx

http://www.wintellect.com/CS/blogs/jprosise/archive/2009/11/25/silverlight-4-s-new-clipboard-support.aspx

http://www.silverlight.net/learn/videos/silverlight-4-beta-videos/datagrid-enhancements/

Wednesday, January 20, 2010

Balsamiq Mockups - Great Wireframe tool

I started playing with Microsoft’s  prototyping tool, and I must say… it’s cool, it’s powerful, but it’s also complicated! I’ve only spent a couple of hours working on it, so I’m sure (just like Expression Blend) if I played with it for a while longer, I would grow to love it. The time constraints I’m currently under do not allow me to spend days trying to learn this new tool. After trying a few other tools, I ran across Balsamiq Mockups. This tool is an extremely easy tool to use and it is relatively cheap. There is also a free version that will meet the needs of most users.

After downloading the tool, I had created several useful wireframes in a matter of minutes. Here are just a few of the sample mockups created with this tool that are displayed on their website:

image

image

If you are a user interface designer, I would highly encourage you to give the free version of this tool a try. It may not be as powerful as Sketchflow, but it’s got all the essentials I was looking for and some of the perks I don’t necessarily need but like.

Wednesday, September 9, 2009

Working with Silverlight 3's DataPager Control

Silverligth 3's DataPager control works great if you are working with the .Net Ria Services. The .Net Ria Services make it easy for you to retrieve data from a db and page it so it is not all retrieved at once (improving performance). But how do you use the control if you want to manually create it yourself? What if you already have your paging scheme implemented and all you wish to do is use a new pager control?

This is relatively simple to do, but it isn't the most elegant code. You will need to use a PagedCollectionView. This is what you have to set the source to in your pager in order to get it to work. In order to use this class, you will need to add the following using statement to your source file.

using System.Collections.Specialized;

Once you have that, you can create a PagedCollectionView by passing an array to the constructor. In this example, I have an integer array (pagerSource) which is filled with a bunch of 1's. You could really put whatever you want in here. You can make it any type of array too, I just chose and integer one. Once I have my array the appropriate length (length will equal the pager's # of pages), I can create the PagedCollectionView object and set that as the source of my pager. I can then assign event handlers as you would expect to see when the pageIndex changes and perform my logic accordingly.

Enjoy!

int totalPages =  .//... logic to figure out my # of pages

int[] pagerSource = new int[totalPages];
for (int i = 0; i < totalPages; i++)
{
     pagerSource[i] = 1;
}

pagedCollectionView = new PagedCollectionView(pagerSource);
myPager.Source = pagedCollectionView;

Thursday, September 3, 2009

This Saved My Neck!

Just a quick post in case you are ever in the situation I was in today. I was told to have a presentation ready in a couple of days to present to management in our company. Great. I have had those materials prepared for a while, so all I have to do is tweak them a bit and I'm ready to go... WRONG! I somehow lost all my files. The directory where I had my presentation saved vanished!!!

I searched for a while for applications to recover my deleted files. I found a few that looked ok, so I downloaded the trials. I started searching my pc, but it was taking forever (and I did not have that kind of time). I finally remembered a Vista commercial that briefly mentioned something about how easy Vista makes it to recover deleted files, so I started searching for that. With that search I found ShadowExplorer. Now, the first post I saw on it mentioned that it was built in to all of the versions of Vista, but I did not see it in mine (Vista Business). I searched for a download of it and found this site...

http://forums.techarena.in/tips-tweaks/1063644.htm

From there, I was able to download the latest version and recover my files with just a few clicks of the mouse!!!

ShadowExplorer is a life-saver, so I thought I'd share in case anyone else finds themselves in a similar conundrum.

Enjoy!!!!