Tuesday, May 19, 2009

ElementMenu in Microsoft Surface

Microsoft Surface 1.0 SP1 introduced a new control named ElementMenu.ElementMenu in surface SDK provides you a new way to display the data in a new hierarchical manner.ElementMenu implementing SurfaceItemsControl and its a collection of ElementMenuItem.I created a sample application using this ElementMenu just to checking out how its looking.Of course its pretty cool.

Create a Surface Project.In surfaceWindow1 add ElementMenu Control from Toolbox.

<s:ElementMenu Name="MainMenu">

</
s:ElementMenu>
Add child ElementMenuItem controls.

<s:ElementMenu Name="MainMenu"
VerticalAlignment="Bottom">
<
s:ElementMenuItem Header="Honda">
<
s:ElementMenuItem x:Name="MenuItem1"
Header="Civic"
Click="MenuItem1_Click" />
<
s:ElementMenuItem Header="CRV"
Command="local:SurfaceWindow1.MenuItemCommand" />
<
s:ElementMenuItem Header="City"
Click="MenuItem1_Click" />
<
s:ElementMenuItem Header="Accord"
Command="local:SurfaceWindow1.MenuItemCommand" />
</
s:ElementMenuItem>
</s:ElementMenu>
Here i added two levels of ElementMenuItem for the ElementMenu.We can handle the click event by either using Click Event handler or using Command.Here i am using both for different Element Menu Items.Using Click Event handler is straight forward.But if we are using command first create a RoutedCommand in the code behind,

public static readonly RoutedCommand MenuItemCommand = new RoutedCommand();
Then add this command to the Window’s CommandBindings.Here am using XAML for adding the command to the command collection,

<Window.CommandBindings>
<
CommandBinding Command="local:SurfaceWindow1.MenuItemCommand"
Executed="CommandBinding_Executed" />
</
Window.CommandBindings>
where local is the reference to the current assembly,

xmlns:local="clr-namespace:MySurfaceApplication"
SurfaceWindow1 is the Class name.Add this command to the Element Menu Item as in the above code snippet.Add CommandBinding_Executed in the code behind,

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
CarDetails.Text = (e.OriginalSource as ElementMenuItem).Header.ToString();
}
So now my whole XAML looks like,

<s:SurfaceWindow x:Class="MySurfaceApplication.SurfaceWindow1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="http://schemas.microsoft.com/surface/2008"
xmlns:local="clr-namespace:MySurfaceApplication"
Title="MySurfaceApplication">
<
Window.CommandBindings>
<
CommandBinding Command="local:SurfaceWindow1.MenuItemCommand"
Executed="CommandBinding_Executed" />
</
Window.CommandBindings>

<
Grid>
<
Grid.RowDefinitions>
<
RowDefinition />
<
RowDefinition />
</
Grid.RowDefinitions>
<
TextBlock x:Name="Comparison"
Grid.Row="0"
Text="Car Comparison"
VerticalAlignment="Bottom"
HorizontalAlignment="Center"
Foreground="White"
Background="Blue">
<
s:ElementMenu Name="MainMenu"
VerticalAlignment="Bottom"
ActivationMode="HostInteraction"
ActivationHost="{Binding ElementName=Comparison}">
<
s:ElementMenuItem Header="Honda">
<
s:ElementMenuItem x:Name="MenuItem1"
Header="Civic"
Click="MenuItem1_Click" />
<
s:ElementMenuItem Header="CRV"
Command="local:SurfaceWindow1.MenuItemCommand" />
<
s:ElementMenuItem Header="City"
Click="MenuItem1_Click" />
<
s:ElementMenuItem Header="Accord"
Command="local:SurfaceWindow1.MenuItemCommand" />
</
s:ElementMenuItem>
</
s:ElementMenu>
</
TextBlock>
<
TextBlock x:Name="CarDetails"
Height="200"
Width="200"
Grid.Row="1"
Text="Car Details"
VerticalAlignment="Center"
Background="DarkRed"
HorizontalAlignment="Center" />
</
Grid>
</
s:SurfaceWindow>
and code behind like(using directives removed),

namespace MySurfaceApplication
{
/// <summary>
///
Interaction logic for SurfaceWindow1.xaml
/// </summary>
public partial class SurfaceWindow1 : SurfaceWindow
{
public static readonly RoutedCommand MenuItemCommand = new RoutedCommand();
/// <summary>
///
Default constructor.
/// </summary>
public SurfaceWindow1()
{
InitializeComponent();
// Add handlers for Application activation events
AddActivationHandlers();

}


/// <summary>
///
Occurs when the window is about to close.
/// </summary>
/// <param name="e"></param>
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);

// Remove handlers for Application activation events
RemoveActivationHandlers();
}

/// <summary>
///
Adds handlers for Application activation events.
/// </summary>
private void AddActivationHandlers()
{
// Subscribe to surface application activation events
ApplicationLauncher.ApplicationActivated += OnApplicationActivated;
ApplicationLauncher.ApplicationPreviewed += OnApplicationPreviewed;
ApplicationLauncher.ApplicationDeactivated += OnApplicationDeactivated;
}

/// <summary>
///
Removes handlers for Application activation events.
/// </summary>
private void RemoveActivationHandlers()
{
// Unsubscribe from surface application activation events
ApplicationLauncher.ApplicationActivated -= OnApplicationActivated;
ApplicationLauncher.ApplicationPreviewed -= OnApplicationPreviewed;
ApplicationLauncher.ApplicationDeactivated -= OnApplicationDeactivated;
}

/// <summary>
///
This is called when application has been activated.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnApplicationActivated(object sender, EventArgs e)
{
//TODO: enable audio, animations here
}

/// <summary>
///
This is called when application is in preview mode.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnApplicationPreviewed(object sender, EventArgs e)
{
//TODO: Disable audio here if it is enabled

//TODO: optionally enable animations here
}

/// <summary>
///
This is called when application has been deactivated.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnApplicationDeactivated(object sender, EventArgs e)
{
//TODO: disable audio, animations here
}

private void MenuItem1_Click(object sender, RoutedEventArgs e)
{
CarDetails.Text = (e.OriginalSource as ElementMenuItem).Header.ToString();
}

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
CarDetails.Text = (e.OriginalSource as ElementMenuItem).Header.ToString();
}
}
}

Build and Run the application.thumbs_up

3 comments:

Anonymous said...

Oi. Parabéns por seu excelente blog. Gostaria de lhe convidar para visitar meu blog e conhecer alguma coisa sobre o Brasil e nossa luta contra o comunismo. Abração

Unknown said...

As a .NET developer, do you know if similar control exist in WPF4? If not, what would be the way to write it?
Thanks.
surfgal

AJ said...

Valeriy,
AFAIK there is no such controls in WPF and also its purely for Surface. Usually we don't use similar controls in WPF. But if you want one, then you can try a custom control with some custom logic:-)

Post a Comment