I am having issues getting an ICommand, in this case a MVVMLight RelayCommand, to fire in the ViewModel from a ControlTemplate in my Silverlight application.
Everything on the UI renders correctly but when clicking the Telerik RadMenu item with an embedded button the LoadTopFiveFaults method on the ViewModel does not fire.
Should I be using a RelativeSource in the ControlTemplate? Is so what am I missing? Any better ways to do this?
Control Template
<ControlTemplate x:Key="SubMenuItem" TargetType="telerik:RadMenuItem">
<Grid>
<Grid x:Name="ContentGrid" Margin="{TemplateBinding Padding}">
<Button Height="70" Style="{StaticResource MenuButtonStyle}" Margin="2"
CommandParameter="{Binding ID}"
Command="{Binding DataContext.MenuCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=navigation:Page}}">
</Button>
</Grid>
</Grid>
</ControlTemplate>
ControlTemplate Button Style
<!--MenuButton-->
<Style x:Key="MenuButtonStyle" TargetType="Button">
<Setter Property="Background" Value="#FF1F3B53"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0"/>
<GradientStop Color="#FF8399A9" Offset="0.375"/>
<GradientStop Color="#FF718597" Offset="0.375"/>
<GradientStop Color="#FF617584" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundAnimation"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundAnimation"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To=".55" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisualElement"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualElement"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Background" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" BorderBrush="Black">
<Grid Margin="1">
<Border x:Name="BackgroundAnimation" Background="#FFF7B000" Opacity="0"/>
<Rectangle x:Name="BackgroundGradient" Fill="{StaticResource PageBackground}"/>
</Grid>
</Border>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Rectangle x:Name="DisabledVisualElement" Fill="#FFFFFFFF" IsHitTestVisible="false" Opacity="0" RadiusY="3" RadiusX="3"/>
<Rectangle x:Name="FocusVisualElement" IsHitTestVisible="false" Margin="1" Opacity="0" RadiusY="2" RadiusX="2" Stroke="#FF6DBDD1" StrokeThickness="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Silverlight Page
<navigation:Page x:Class="QSmart_Cabs_Viewer.Views.Report"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:local="clr-namespace:QSmart_Cabs_Viewer.Views"
xmlns:viewmodels="clr-namespace:QSmart_Cabs_Viewer.ViewModels"
d:DesignWidth="640" d:DesignHeight="480" mc:Ignorable="d"
Title="QSmart Cab Systems Report">
<navigation:Page.Resources>
<viewmodels:ReportPageViewModel x:Key="ViewModel" />
</navigation:Page.Resources>
<Border x:Name="ReportBorder" BorderBrush="Black" BorderThickness="3" CornerRadius="10" Background="{StaticResource PageBackground}">
<Border.Effect>
<DropShadowEffect Direction="318"/>
</Border.Effect>
<Grid x:Name="LayoutRoot" DataContext="{StaticResource ViewModel}" Background="{StaticResource PageBackground}">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="33*"/>
<RowDefinition Height="40*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="ConfigTitle" Text="QSmart Cabs Report"
Grid.Row="0" Grid.ColumnSpan="3"
FontSize="32" TextAlignment="Center"
VerticalAlignment="Center" Foreground="{StaticResource ReportHeaders}" />
<Border Grid.Row="0" Grid.Column="3" Grid.RowSpan="3"
BorderBrush="{StaticResource JCBOrangeBoarder}" Background="{StaticResource JCBOrange}"
Margin="3" BorderThickness="5" CornerRadius="20">
<telerik:RadMenu x:Name="Businesses" IconColumnWidth="0" HorizontalAlignment="Left"
ItemsSource="{Binding MenuItems}" ItemContainerStyle="{StaticResource ItemStyle}"
Margin="5,10" Background="{x:Null}" Orientation="Vertical" ClickToOpen="True">
</telerik:RadMenu>
</Border>
</Grid>
</Border>
</navigation:Page>
View Model
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using QSmart_Cabs_Viewer.Helpers.IOC;
using QSmart_Cabs_Viewer.Helpers.Menus;
using QSmart_Cabs_Viewer.Models;
using QSmart_Cabs_Viewer.ServiceAgents;
using QSmart_Cabs_Viewer.Web.Models;
namespace QSmart_Cabs_Viewer.ViewModels
{
public class ReportPageViewModel : ViewModelBase
{
private const string _topFiveCaption = "Top 5 Faults @ {0}";
private const string _narrativeCaption = "Top Faults @ {0}";
private string _topFiveTitle;
private string _narrativeTitle;
private IDataAgent ServiceAgent { get; set; }
private IMenuBuilder MenuBuilder { get; set; }
public ObservableCollection<MenuModel> MenuItems { get; set; }
public ReadOnlyObservableCollection<CabFaultsCountByBusiness_Result> FaultCountByCustomer { get; set; }
public ICommand MenuCommand { get; set; }
public string TopFiveTitle
{
get
{
return _topFiveTitle;
}
private set
{
_topFiveTitle=string.Format(_topFiveCaption,value);
_narrativeTitle = string.Format(_narrativeCaption, value);
RaisePropertyChanged("TopFiveTitle");
RaisePropertyChanged("NarrativeTitle");
}
}
public string NarrativeTitle
{
get
{
return _narrativeTitle;
}
}
public ReportPageViewModel()
{
if (!IsInDesignMode)
{
ServiceAgent = UnityComponentContainer.ResolvePart<IDataAgent>();
MenuBuilder = UnityComponentContainer.ResolvePart<IMenuBuilder>();
LoadStaticData();
TopFiveTitle = "All Customers";
MenuCommand = new RelayCommand(() => LoadTopFiveFaults());
}
}
private void LoadStaticData()
{
ServiceAgent.GetBusinessUnit((cb) => CreateMenuItems(cb.Entities));
ServiceAgent.GetFaultsCountByBusiness((fcb) =>
FaultCountByCustomer = (ReadOnlyObservableCollection<CabFaultsCountByBusiness_Result>)fcb.Entities);
}
private void CreateMenuItems(IEnumerable<BusinessUnit> items)
{
MenuItems = MenuBuilder.Create(items);
}
private void LoadTopFiveFaults()
{
TopFiveTitle = "Command Fired";
}
}
}