Get Microsoft Silverlight

Tuesday, August 04, 2009

Silverlight 3 Multi-Touch with Windows 7 and HP Touch Smart.

Inspired by the blog Silverlight 3 Multi-touch: The Basics by Tim Heuer, I thought of experimenting with it and creating a small sample. The logic is pretty simple, I have used TranslateTranform and ScaleTranform to do the movement and scaling respectively. When the TouchAction is Move we can distinguish whether it is a single touch or multi touch from the TouchPointCollection count. When it is a double touch you can calculate the change of distance between the two touch points and transform that as ScaleTransform of the Visual. Please watch the video, I shot on my office HP Touch smart machine.

Have you got a multi-touch monitor?, then run the application here and feel the Silverlight touch. You can set your browser in Full-Screen mode to get a good experience. Please note that the current Silverlight version doesn't accept Touch inputs while running in Silverlight full screen mode(ie, App.Current.Host.Content.IsFullScreen =true). You can read more on Silverlight multi touch on MSDN

Click here to run the application

image

Thursday, July 30, 2009

Slider Preview as Expression Blend 3 Behavior

Behaviors is one of the new features Expression blend 3 has introduced to make interactivity easy. Behavior allows us to wrap the interaction logic as a very discrete unit and attach to any UI elements. My previous blog post about Attaching preview behavior to a Slider control, is a good scenario to make as a Behavior. I have used Attached Dependency property as a technique to make it happen in the earlier post, though the concept is almost same but Blend Behavior gives a neat and clean abstraction. It also allows a Blend user to just drag-drop to any Slider control. So this is a great functionality which helps boost the re-usability in a cool way.

Problem : Create a behavior to display the value of a Slider control when hover over.

First step is to make a class which derived from Behavior class. public class PreviewSliderBehaviour : Behavior<Slider> Here I am explicitly giving Slider class as my targeted UI Element type since this behavior is meaningless to other elements. Now we need to override two methods of Behavior class, protected override void OnAttached() and protected override void OnDetaching() . I can subscribe mouse events in the OnAttached() method and unsubscribe the same in the OnDetaching() method.

     protected override void OnAttached()
{
m_attachedObject = AssociatedObject;
// Gives you the instance of the Slider you attached this behavior on to

if (m_attachedObject != null)
{
m_attachedObject.PreviewMouseMove +=
new System.Windows.Input.MouseEventHandler(item_PreviewMouseMove);
m_attachedObject.MouseLeave +=
new System.Windows.Input.MouseEventHandler(item_MouseLeave);
}
base.OnAttached();
}
/// Called when the behavior is removed from the DependencyObject
protected override void OnDetaching()
{
if (m_attachedObject != null)
{
m_attachedObject.PreviewMouseMove -=
new System.Windows.Input.MouseEventHandler(item_PreviewMouseMove);
m_attachedObject.MouseLeave -=
new System.Windows.Input.MouseEventHandler(item_MouseLeave);
}
base.OnDetaching();
}

The important logic lies in the MouseMove handler, it creates a ContentAdorner(a custom adorner, you can see in the source code) and sets the value calculated here to the ContentAdorner.Content property. This also sets the ContentAdorner’s placement point to the mouse point so that the adorner moves along with the mouse move.

     void item_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
Slider slider = sender
as Slider;
if (popup == null)
{
//Creates a new ContentAdorner with the given Style, Content Style is a Dependancy property of this behaviour
popup =
new ContentAdorner(slider, ContentStyle);
AdornerLayer layer = AdornerLayer.GetAdornerLayer(slider);
layer.Add(popup);
}
popup.Visibility = Visibility.Visible;
//Finding out the PART_Track from the controltemplate of the Slider
Track _track = slider.Template.FindName(
"PART_Track", slider) as Track;
//Calculates the mouse position
Point position = e.MouseDevice.GetPosition(_track);
//This method gives the exact preview value of the Slider
double value = _track.ValueFromPoint(position);
if (slider.SmallChange != 0.0)
{
double diff = value % slider.SmallChange;
value -= diff;
}
//Setting the value as the content of the ContentAdorner
popup.Content = Math.Max(slider.Minimum, Math.Min(slider.Maximum,
value));
position = e.GetPosition(slider);
position.Y = slider.ActualHeight / 2.0;
popup.PlacementOffset = position;
}

Now it is pretty easy to add this behavior to any Slider control, if you are in Expression Blend just opens the behavior tab and drag and drop this on to any Slider in the designer area. The XAML code will looks like,

<Slider x:Name="sld" Minimum="00" Maximum="100"    SmallChange="0.5" IsSnapToTickEnabled="True" TickFrequency="0.5">
<i:Interaction.Behaviors>
<local:PreviewSliderBehaviour ContentStyle=
"{StaticResource PreviewStyle}"/>
</i:Interaction.Behaviors>

</Slider>

Source Code

Few other links you may be interested to read about Behaviors

Gallery of Behaviors

AN INTRODUCTION TO BEHAVIORS, TRIGGERS, AND ACTIONS

Using a Behavior to magnify your WPF applications

Wednesday, July 29, 2009

Attaching Preview behavior to a WPF Slider control

PreviewSlider PreviewSlider1

Today I am sharing about a common usage of Slider control for the Timeline scenarios as we can see in many Media players. The above pictures shows timeline/scrubber control of some popular video players(Hulu and Youtube). We can edit the Slider Style and ControlTemplate to create the same look and feel of the above two scrubbers except the preview value get displayed when we hover over.

While figuring out an easy way to build this, I got two different options. The first and the obvious solution is to extend the Slider class to create a new custom control, which will have a new DependancyProperty called PreviewValue to hold the mouse over value. The biggest challenge in this approach is to make this control as much flexible(design and dev friendly) because people may customize the control by giving different Size and Margins to the Track and other parts of the Control template, which will make our assumptions invalid in some cases. And another issue is having a totally modified Controltemplate for the new Slider makes ‘Integrators’ life hard, because this control will introduce one mandatory visual inside the control template with a PART_naming convention.

Would it be cool if we can achieve this by adding couple of Attached properties to any regular Slider control? Yes that seems to be an elegant solution to me. So I have created a static class -PreviewSliderHelper to hold the required attached dependancy properties. The XAML code for the Slider is shown below. You need to specify a Style in the resource which will set to the preview display visual. The tooltip like visual is created using a custom Adorner and repositioning it based on the mouse move, I will discuss the details about this generic adorner implementation in another blog post.

image

And the final UI came out like this. Get the Executable

Jobi_mediaPlayer

The main technical details you might wanted to know is how to grab the preview value on the mouse over. We have to find out the PART_Track inside the slider and call ValueFromPoint() function to get the exact Slider.Value for each mouse move.

image 

Source Code -Of course there are lot to improve on this messy code :) ,but feel free to share your thoughts on this

Friday, July 17, 2009

An easy way to update all the UI Property Bindings of an Instance at once! – Silverlight and WPF

Imagine that you have a lot of properties in a class and you are very sure that all of those properties are getting updated at the same point of time. What generally we do in the ViewModel scenario is that we create Property setters for all these and raise PropertyChanged event so as to get the data reflected in the UI layer bindings. But that is a real resource waste when you really know the time of all your property updates. The solution is really easy as per the MSDN documentation for PropertyChanged Event in the remarks section it says “The PropertyChanged event can indicate all properties on the object have changed by using either a null reference (Nothing in Visual Basic) or String.Empty as the property name in the PropertyChangedEventArgs.” It seems that this is a great saver in terms of code writing and execution, since we need to raise only one PropertyChanged Event per class just after the property updation.

Think about a Stock Trading scenario as an example to this, you must have a Quote class which generally will have lot of properties in it, and there will be an Update method on a timer may update this quote object. Imagine that this class is bound to a DataTemplate at XAML level.

    public class Quote : ViewModelBase
{
public string Symbol { get; set; }
public double Last { get; set; }
public double Change { get; set; }
public double Bid { get; set; }
public double Ask { get; set; }
public double Open { get; set; }
public string Percentage { get; set; }
public double Volume { get; set; }

public bool IsRefreshed
{
get { return _isRefreshed; }
set
{
_isRefreshed = value;
RaisePropertyChanged(null);
}
}
private bool _isRefreshed;
}

Isn't the code very neat with the awesome Auto-Implemented Properties rather than having fields and expanded setters with RaiseProertyChanged in all those?. Now in the Stock Update method you can set all these properties and set IsRefreshed=true which in turn calls RaisePropertyChanged(null) and makes the WPF/Silverlight binding infrastructure to re-evaluate all the bindings associated with the UI.

I recommend using the MVVM implementation by Josh Smith for the basic ViewModel architecture. You can download his MVVM Foundation from codeplex - http://mvvmfoundation.codeplex.com/

Tuesday, April 07, 2009

3D Flipper Control – Using Silverlight 3.0 Plane Projection

Silverlight 3.0 has a coolest feature called PlaneProjection-a perspective transform which projects any UIElement on to a 3D plane. To create a plane projection you just need to set an attached property called ‘Projection’ on the UI Element. You can see relevant set of properties to rotate, center or offset. If you are using Expression blend 3 Beta, you can set these properties using the new Projection editor under Transform category of the property editor.

image image

I am going to create a 3D flipper control using this plane projection feature. I guess 3D flipping is the most popular and simplest 3D UX pattern out there. In a nut shell what we need is a custom Silverlight control which is able to take a ‘Front’ and ‘Back’ content elements. And the control should have the ability to flip both the contents in a 3D plane. For example if I have two images to flip, then my XAML should be as follows.

image

So I need to define two dependency properties of type UIElement called FrontContent and BackContent. As for every look less control, we need to define a default XAML Style and control template for this control in Themes\Generic.xaml file. In the template we need two ContentPresenter for the control to respect both front and back Content which user sets. And the root element is where we can apply the PlaneProjection.

image

The remaining jobs are to rotate the PART_MainGrid with an animation on the (PlaneProjection.RotationY) from 0 to 180degrees and when it reaches 90degrees, we need to flip the visibility of the contents so that the back content should be visible from 90 to 180 transition. These two actions can purely be handled using VisualStateManager in XAML. Currently I am triggering the Flip action on mousedown event, but we can utilize some Command pattern to make it fully generic. You may notice that I put a ScaleTransform with ScaleX=-1 to the backside container in the above XAML. The reason is that when the PlaneProjection flips to the backside the content gets flipped horizontally, so we are applying a horizontally flipped(ScaleX =-1) container to the backside so that the user applied BackContent will look normal.

See the demo here 

And here is the Source Code

I have used few other Silverlight3.0 features in this sample. Effects(Dropshadow effect) and ElementName binding. You can type on the TextBox bellow and the value has bind to a TextBlock on the backside content. ElementName binding feature makes the binding in Silverlight a lot more easier as it is with WPF.

image

Saturday, March 07, 2009

Different ways to access XML data in Silverlight Application

One of the most common requirement in the Silverlight development is to load XML data in to the application. I am going to describe a few different options that we can choose based on the situations. I am using LINQ for the XML parsing in the examples. Taking a sample XML file names Sample.xml with the following content

<Employees>
<Employee Name="John"/>
<Employee Name="Mark"/>
<Employee Name="David"/>
</Employees>

1. Load XML file directly from the Web Server hosted Silverlight XAP

You can host the XML file at your web server itself and Silverlight application can load it on demand. To simulate this in Visual Studio you need to create a Test Website for your Silverlight application and put xml file into the ClientBin folder.

image

Now we can write few lines of code to read the XML. WebClient will download the file asynchronously

void Page_Loaded(object sender, RoutedEventArgs e)
{
WebClient xmlClient = new WebClient();
xmlClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(XMLFileLoaded);
xmlClient.DownloadStringAsync(new Uri("Sample.xml", UriKind.RelativeOrAbsolute));
}
void XMLFileLoaded(object sender, DownloadStringCompletedEventArgs e)
{
string XmlString = e.Result; // Got all your XML data in to a string
XDocument elem = XDocument.Load(XmlReader.Create(new StringReader(XmlString)));
var collection = from nod in elem.Descendants("Employee")
select nod.Attribute("Name").Value;
lstBox.ItemsSource = collection ; // XML data bind to the UI
}

2. Load XML file directly from the Silverlight App(XAP)

image

Add the XML file as a content to the Silverlight project. This is the easiest way to build and deploy a Silverlight project, since you really don't need to worry about the XML file once it is placed as part of the project. When you compile, it will automatically embed the XML file inside the XAP file. But the big problem is that you can’t easily change the XML data after the deployment. . And here the C# to read data from this situation

 XDocument elem = XDocument.Load("Sample.xml");
var collection = from nod in elem.Descendants("Employee")
select nod.Attribute("Name").Value;

3. Load XML file from one of the Silverlight Assemblies

When you have more than one Silverlight class libraries associated with a Silverlight application, it may be meaningful to add the XML file to a different project than the main project. So this case you need to add the file as an EmbeddedResource.

image

  Stream stream = this.GetType().Assembly.GetManifestResourceStream("XmlLoadingTest.Sample.xml");
XDocument elem = XDocument.Load(XmlReader.Create(stream));
var coll = from nod in elem.Descendants("Employee")
select nod.Attribute("Name").Value;

4. Load XML file from a URI

This is the case of accessing third party data from feeds and services. It is a big security threat to access resources from a server where the XAP file didn't not originate. So the server you are requesting access needs a special permission files hosted. You can read more about this here-Making a Service Available Across Domain Boundaries) and here-Network Security Access Restrictions in Silverlight 2

When coming to read this kind of hosted XML urls from C#, you can use either step(1) or step(2) of the above C# code snippets. I prefer the step(1) option because it is asynchronous and will not hang up the UI. And also it will not make the XAP size larger with larger XML files, so the initial loading will be faster.

Sunday, March 01, 2009

Sunny Orange - WPF Theme 1

Recently I found out that I have an old blog post about Control Templating a Button, getting a lot of hits. Many out there are looking for free control templates and themes for WPF/Silverlight applications. I am planning to publish few WPF/Silverlight themes in the coming posts. So here I am publishing a simple theme which has almost similar colors to the old blog post. It contains very basic set of controls. 
1)Button
2)ToggleButton
3)ComboBox
4)TextBox
5)CheckBox
6)RadioButton
7)ScrollBar
8)ScrollViewer
9)ListBox
10)ProgressBar
11)Slider

You can find the source XAML style here - SunnyOrange_Theme.xaml
WPF control theming and templating is very interesting and fun task in the WPF application development, it took only an hour or two for me to create this theme file. Please let me know your valuable feedbacks and suggestions .

Tuesday, February 03, 2009

A simple Multiselect ComboBox using expression Blend



I have often seen requirements to have a combobox with multiple selection enabled. We know thatWPF ListBox control is having two special properties, which enables the multiple selection but the combobox doesnt have those
public IList SelectedItems { get; }
public SelectionMode SelectionMode { get; set; }
There are many ways we can make a multiselect combo box
1)Create a custom control from the scratch and have a Listbox in the dropdown
2)Extend the combobox and add the above properties to it
3)Edit the Combobox control template to add necessary controls and binding.

I am going to describe the 3rd idea from the above list, which is a total Expression Blend work, so no need of VS2008 to make a multiselect combobox from a simple combobox.

Place a combobox in to the editing area and right click on the control to create an copy of the Control template. Now you can see the Control's tree on the left side of Expression Blend



The ItemPresenter inside the scrollviewer is actually the control which displays the data in the dropdown part of the combobox, we want to havethe multiselection enabled on that. So replace the ItemsPresenter with a ListBox control with SelectionMode=Multiple 
The last control in the tree, ContentPresenter is to show the selectedvalue in the combobox's main area. Since we are going to have more than one value from the ListBox we need to have an ItemsPresenter like control here. Just for simplicity I have replace it with an ItemsControl with a an ItemsPanel as StackPanel with horizontal orientation.
Now we need to bind the ListBox.SelectedItems to the ItemsControl using an ElementName binding.



<Style x:Key="MultiSelectComboBox" TargetType="{x:Type ComboBox}">

<Setter Property="Template">

<Setter.Value>

<ControlTemplate TargetType="{x:Type ComboBox}">

<Grid SnapsToDevicePixels="true" x:Name="MainGrid" Height="Auto" Width="Auto">

<Grid.ColumnDefinitions>

<ColumnDefinition Width="*"/>

<ColumnDefinition Width="0"/>

</Grid.ColumnDefinitions>

<Popup AllowsTransparency="true" IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"

Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}"

Margin="1" x:Name="PART_Popup" Grid.ColumnSpan="2">

<Border x:Name="DropDownBorder" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding Path=ActualWidth, ElementName=MainGrid}">

<ScrollViewer CanContentScroll="true">

<ListBox x:Name="lstBox" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"

KeyboardNavigation.DirectionalNavigation="Contained" SelectionMode="Multiple" ItemsSource="{TemplateBinding ItemsSource}"/>

</ScrollViewer>

</Border>

</Popup>

<ToggleButton Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Grid.ColumnSpan="2"

  IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{DynamicResource ToggleButtonStyle1}"/>

<ItemsControl IsHitTestVisible="false" ItemsSource="{Binding Path=SelectedItems, ElementName=lstBox}" Margin="4,0,0,0">

<ItemsControl.ItemsPanel>

<ItemsPanelTemplate>

<StackPanel IsItemsHost="True" Orientation="Horizontal"/>

</ItemsPanelTemplate>

</ItemsControl.ItemsPanel>

</ItemsControl>

</Grid>

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>


Now we need to access the SelectedItems from this new control template. Use the bellow line
((ListBox)cmbBox.Template.FindName("lstBox",cmbBox)).SelectedItems
You can download the sample project here

Monday, February 02, 2009

Lilac Chaser - Optical illusion using Silverlight







Get Microsoft Silverlight

"When one stares at the center for about 20 seconds or so, one first sees a gap running around the circle of lilac disks, then a green disk running around the circle of lilac disks, then a green disk running around on the grey background, the lilac disks having disappeared or having been erased by the green disk. This is due to an interesting effect in which the colors of the lilac disks are inverted in the optical illusion to a green color"
This optical illusion is called Lilac chaser . Just thought of creating a silverlight version of this illusion for fun. I have used a radial panel(from my old blog) to layout the ellipses radially, and implemented a a timer to change the visibility in a sequential way.

This kind of effects can be a good candidate for Splash sreen for silverlight applications :)
Full source can be found here