October 2007 - Posts

Perspectives on WPF

While browsing I found an excellent article by Infragistics. The article describes WPF from different perspectives, including Windows Forms Developer, ASP.NET Developer and a Visual Designer. It is truly a excellent read:

http://community.infragistics.com/uploadedFiles/Community/Downloads/7471/Perspectives%20On%20WPF.xps

Also have a look at the following companies WPF demos:

http://www.vertigo.com/

http://www.infragistics.com/

http://www.thirteen23.com/

 

Posted by rudi | with no comments
Filed under:

Using TextEffect to animate text

TextEffect can be used to apply transforms to parts of a TextBlock. TextEffect can also be animated to create "moving" text that can create some very unique effects. As pointed out by Filipe Fortes's blog article, note the following about TextEffect:

1) The transform effect is always relative to the beginning of the line. This had me confused when I started to use the TextEffect. I wanted to create an effect where an animation runs from the first character to the last and each character rotates and then fades away. What I then discovered, is that the character would actually do a rotate around the beginning of the line which looks weird!

2) Any size or layout changes will not affect the layout of the text. Once my first attempt at the rotate failed, I thought I would try and make each letter inflated and then deflate... This works cool but because the text layout is not affected, the inflated letter overlaps the other content! It also looks weird!

Well, now that we have all the negatives out of the way... how do I make my text move in a wave?

First off we need a TextBlock with some text in

<TextBlock x:Name="txtBlock" Text="WPF is very cool!!!" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="36" Loaded="txtBlock_Loaded" />

Next, use the OnLoaded event of the TextBlock to start the animation

Storyboard storyboard = new Storyboard();
storyboard.RepeatBehavior = RepeatBehavior.Forever;
storyboard.AutoReverse = true;

txtBlock.TextEffects = new TextEffectCollection();

for (int i = 0; i < txtBlock.Text.Length; i++)
{
    TextEffect effect = new TextEffect();
    effect.PositionCount = 1;
    effect.PositionStart = i;
    
    effect.Transform = new TranslateTransform();
    txtBlock.TextEffects.Add(effect);

    DoubleAnimation animation = new DoubleAnimation(0, 20, new Duration(TimeSpan.FromSeconds(1)));
    animation.AccelerationRatio = 0.5;
    animation.DecelerationRatio = 0.5;
    animation.AutoReverse = true;
    animation.RepeatBehavior = RepeatBehavior.Forever;              
    animation.BeginTime = TimeSpan.FromSeconds(i * 0.25);
    Storyboard.SetTargetName(animation, "txtBlock");             
    
    string path = String.Format("TextEffects[{0}].Transform.Y",i);
    PropertyPath propPath = new PropertyPath(path);
    Storyboard.SetTargetProperty(animation, propPath);
    storyboard.Children.Add(animation);
}
storyboard.Begin(this);

And the final animation looks something like this

You actually have to run the code to really see the animation... the screen capture just doesn't do it justice! This is a very basic example of how it can be used... Before venturing to far into the TextEffect, first see if a RenderTransform or LayoutTransform is not enough!!! I only found the TextEffect useful when I started working at a per character level!

Also have a look at Filipe Forte's article and Josh Smith also has a sample application he build (based on a sample from Chris Anderson's book)

Posted by rudi | 1 comment(s)
Filed under:

HP uses XPE

Just to show the growth of XPE, HP has just received a Technology award from Microsoft for their new printer running XPE:

"HP recently released a multifunction print device that uses the Microsoft Windows® XP Embedded operating system. The new multifunction print device provides better integration with Microsoft products, improved manageability, easier support and a better user experience. HP's device takes advantage of the Microsoft Windows Embedded family of operating systems."

Nice, hopefully this will happen more often now...

Posted by rudi | with no comments
Filed under: ,

How to make a photo rotate in 3D

Blend is an amazing tool... To demonstrate the power of the tool, just try and make a photo rotate in 3D without using blend!

I created a blank WPF project using blend and added a photo to the project. Insert this photo into the window. Also change the size of the image to 200x300, forced the fill to be uniform and placed the image in the middle of the window (set margings to 0).

Please note that this image can also easily be bound to a data source, I just used a static image to demonstrate the 3D rotate

Next, select the image control, and then use the Tools option of making the image 3D

This tools option converts the image to a 3D viewport and then adds the image to a plane. To get an idea of how the 3D viewport works, select the ModelContainer -> Content -> Model in the Objects and Timelines pane and drag the grab handles that appear on the image to manipulate it in 3D. If you need to place an image at a slight angle or need to create any 3D effect, this is a good place to start and play...

Now we need to create a new timeline and make the image rotate. The timeline I created is Window.Loaded but any event can be used to trigger this timeline (A popular event to use is the ListBox.SelectionChanged).

 

Create a key frame at 0 seconds and then apply a rotate transform on either the X or Y axis of 180 degrees. This will basically show the back of the photo.

Next move the timeline to 2 seconds and record another key frame. Now apply a rotate transform again but this time change it to 360 degrees to turn the photo back to normal.

Now run the program...

That is all that is required to make your image rotate in 3D, amazing but so easy to do!!!

PS. For the more hardcore WPFers, have a look at the XAML that blend creates to get a idea of how it works...

Posted by rudi | 1 comment(s)
Filed under: ,

Threading in WPF

While writing my XPe talk, I ran into an interesting problem using WPF... I have a Bluetooth OBEX listener that sits and listens for objects, once this object is received, it gets saved to disk and the URI gets placed into a ObservableCollection<> and then gets data bound to a list box. The natural assumption is that the list box would be updated automatically once a new file is received, but it doesn't!!

The problem is that WPF is a STA application and no other thread except the UI thread can update UI controls (This is called thread affinity). WPF has done an excellent job of trying to eliminate the need for multiple threads but unfortunately it doesn't work for all scenarios!

All WPF applications basically have 2 threads: one for handling rendering and another for managing the UI.  The rendering thread effectively runs hidden in the background while the UI thread receives input, handles events, paints the screen and runs application code

The UI thread queues work items inside an object called a dispatcher.  The dispatcher selects work items on a priority basis and runs each one to completion. Every UI thread must have at least one dispatcher and each dispatcher can execute work items in exactly one thread.

To get around my problem, I basically create a work item that adds the URI to the collection and then ask the dispatcher to execute it. This effectively forces the UI thread to do the work and thus allow my UI to update!

The code is very simple, first you need to create a delegate for the work item and also implement a function that gets executed

public delegate void AddUriDelegate(Uri uri);

public void AddUri(Uri uri)
{
   uris.Add(uri);
}
And then we need to invoke the work item in the thread
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new AddUriDelegate(AddUri), uri);

Now my UI gets updated each time I receive a new data object via Bluetooth!!!

 

Tyler Barton and Nick Kramer has a excellent whitepaper about threading

Build more responsive apps with the dispatcher

Making use of multiprocessing in WPF

Posted by rudi | 3 comment(s)
Filed under: ,

Deploying Silverlight Applications in the Enterprise

As silverlight is increasing in popularity, more and more administrators are asking questions about the deployment (especially in the enterprise environment).

Luckily Dave Tesar wrote an excellent document about deploying Siverlight Applications!

Any system administrator should read this…

 

Posted by rudi | 1 comment(s)
Filed under:

Advertise using Bluetooth

How do you choose which restaurant do you want to eat at in a mall with 100+ restaurants?

Competition in the food industry is very competitive and these businesses are looking at different methods of getting the edge! Some companies have started using Bluetooth as an advertisement medium. The concept is very simple; you walk past a restaurant and your phones Bluetooth is turned on. The restaurant has a system which can detect Bluetooth devices in close proximity and then transmit an advertisement to this device. Now you can get notified of specials that this restaurant is having for the day!

Using InTheHand, this might not be such a difficult system to implement!

Include the correct namespaces

using InTheHand.Net;
using InTheHand.Net.Bluetooth;
using InTheHand.Windows.Forms;

Detect the primary Bluetooth radio

BluetoothRadio br = BluetoothRadio.PrimaryRadio;
br.Mode = RadioMode.Discoverable;

Find a device close by

SelectBluetoothDeviceDialog sbdd = new SelectBluetoothDeviceDialog();
sbdd.ShowAuthenticated = true;
sbdd.ShowRemembered = true;
sbdd.ShowUnknown = true;
if (sbdd.ShowDialog() == DialogResult.OK)
{
   // MORE CODE NEEDED HERE
}

This function creates a dialog box from which you can select the desired Bluetooth device to send the specials too. A fully automated system would need to bypass this step and automatically detect new devices.

Finally we need to send the specials.jpg using OBEX File Push

System.Uri uri = new Uri("obex://" + sbdd.SelectedDevice.DeviceAddress.ToString() + "/" + System.IO.Path.GetFileName(@"C:\specials.jpg"));
ObexWebRequest request = new ObexWebRequest(uri);
request.ReadFile(@"C:\specials.jpg");

ObexWebResponse response = (ObexWebResponse)request.GetResponse();
response.Close();

This code is very basic and still needs some adjustments...

Also have a look at my previous article on using Bluetooth OBEX Listener

kick it on DotNetKicks.com
Posted by rudi | 9 comment(s)
Filed under: