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!
All about GUI's, WPF and Silverlight
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!
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.
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.
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.
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
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.
First, we register the dependency property.
And then we define the HorizontalOffset property.
The VerticalOffset property specifies the amount of vertical space between items within the panel.
First, we register the dependency property.
And then we define the VerticalOffset property.
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.
First, we register the dependency property.
And then we define the SkewYAngle property.
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.
Firs, we register the dependency property.
And then we define the Blur property.
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.
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).
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.
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;
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.
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.
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.
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.
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.
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.
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.
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://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://www.silverlight.net/learn/videos/silverlight-4-beta-videos/datagrid-enhancements/
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:
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.
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;
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!!!!