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";
}
}
}
Your original example seems like it should work. Perhaps the Telerik RadMenu is being built outside of the visual tree ? Not sure.
Try being more explicit to remove the unknown... Name your page (which is bound to your DataContext view model) and try a different binding method:
<Button Height="70" Style="{StaticResource MenuButtonStyle}" Margin="2"
CommandParameter="{Binding ID}"
Command="{Binding DataContext.MenuCommand, ElementName=ReportPage}">
</Button>
Related
I want to improve default datagrid control by some needs like filtering, easy adding-editing etc... I'm trying to customize column headers but couldn't get it. I need to add some other controls to headers and reach them in code side. Is there a way to do this?
Thanks.
<sdk:DataGrid
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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
x:Class="DataGridTest.SLDataGrid"
d:DesignWidth="640" d:DesignHeight="480">
<sdk:DataGrid.Resources>
<Style x:Key="SLDataGridStyle" TargetType="sdk:DataGrid">
<Setter Property="RowBackground" Value="#AAEAEFF4"/>
<Setter Property="AlternatingRowBackground" Value="#00FFFFFF"/>
<Setter Property="Background" Value="#FFFFFFFF"/>
<Setter Property="HeadersVisibility" Value="Column"/>
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="SelectionMode" Value="Extended"/>
<Setter Property="CanUserReorderColumns" Value="True"/>
<Setter Property="CanUserResizeColumns" Value="True"/>
<Setter Property="CanUserSortColumns" Value="True"/>
<Setter Property="AutoGenerateColumns" Value="True"/>
<Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected"/>
<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="BorderThickness" Value="1"/>
<Setter Property="DragIndicatorStyle">
<Setter.Value>
<Style TargetType="ContentControl">
<Setter Property="Foreground" Value="#7FFFFFFF"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SortStates">
<VisualState x:Name="Unsorted"/>
<VisualState x:Name="SortAscending">
<Storyboard>
<DoubleAnimation Duration="0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SortIcon"/>
</Storyboard>
</VisualState>
<VisualState x:Name="SortDescending">
<Storyboard>
<DoubleAnimation Duration="0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SortIcon"/>
<DoubleAnimation Duration="0" To="-.9" Storyboard.TargetProperty="(RenderTransform).ScaleY" Storyboard.TargetName="SortIcon"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="BackgroundRectangle" Grid.ColumnSpan="2" Fill="#66808080" Stretch="Fill"/>
<Rectangle x:Name="BackgroundGradient" Grid.ColumnSpan="2" Opacity="0" Stretch="Fill">
<Rectangle.Fill>
<LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
<GradientStop Color="#FFFFFFFF" Offset="0.015"/>
<GradientStop Color="#F9FFFFFF" Offset="0.375"/>
<GradientStop Color="#E5FFFFFF" Offset="0.6"/>
<GradientStop Color="#C6FFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Grid HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding Content}"/>
<Path x:Name="SortIcon" Grid.Column="1" Data="F1 M -5.215,6.099L 5.215,6.099L 0,0L -5.215,6.099 Z " Fill="#7FFFFFFF" HorizontalAlignment="Left" Margin="4,0,0,0" Opacity="0" RenderTransformOrigin=".5,.5" Stretch="Uniform" VerticalAlignment="Center" Width="8">
<Path.RenderTransform>
<ScaleTransform ScaleY=".9" ScaleX=".9"/>
</Path.RenderTransform>
</Path>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="DropLocationIndicatorStyle">
<Setter.Value>
<Style TargetType="ContentControl">
<Setter Property="Background" Value="#FF3F4346"/>
<Setter Property="Width" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Rectangle Fill="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="GridLinesVisibility" Value="Vertical"/>
<Setter Property="HorizontalGridLinesBrush" Value="#FFC9CACA"/>
<Setter Property="IsTabStop" Value="True"/>
<Setter Property="VerticalGridLinesBrush" Value="#FFC9CACA"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGrid">
<Grid>
<VisualStateManager.CustomVisualStateManager>
<ei:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates" ei:ExtendedVisualStateManager.UseFluidLayout="True">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisualElement"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ValidationStates" ei:ExtendedVisualStateManager.UseFluidLayout="True">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Invalid"/>
<VisualState x:Name="Valid"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2">
<Grid x:Name="Root" Background="{TemplateBinding Background}">
<Grid.Resources>
<ControlTemplate x:Key="TopLeftHeaderTemplate" TargetType="sdk:DataGridColumnHeader">
<Grid x:Name="Root">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border BorderBrush="#FFC9CACA" BorderThickness="0,0,1,0" Background="#FF1F3B53" Grid.RowSpan="2">
<Rectangle Stretch="Fill" StrokeThickness="1">
<Rectangle.Fill>
<LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
<GradientStop Color="#FCFFFFFF" Offset="0.015"/>
<GradientStop Color="#F7FFFFFF" Offset="0.375"/>
<GradientStop Color="#E5FFFFFF" Offset="0.6"/>
<GradientStop Color="#D1FFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Border>
<Rectangle Fill="#FFDBDCDC" Height="1" Grid.RowSpan="2" StrokeThickness="1" VerticalAlignment="Bottom" Width="Auto"/>
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="TopRightHeaderTemplate" TargetType="sdk:DataGridColumnHeader">
<Grid x:Name="RootElement">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border BorderBrush="#FFC9CACA" BorderThickness="1,0,0,0" Background="#FF1F3B53" Grid.RowSpan="2">
<Rectangle Stretch="Fill">
<Rectangle.Fill>
<LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
<GradientStop Color="#FCFFFFFF" Offset="0.015"/>
<GradientStop Color="#F7FFFFFF" Offset="0.375"/>
<GradientStop Color="#E5FFFFFF" Offset="0.6"/>
<GradientStop Color="#D1FFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Border>
</Grid>
</ControlTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<sdk:DataGridColumnHeader x:Name="TopLeftCornerHeader" Template="{StaticResource TopLeftHeaderTemplate}" Width="22"/>
<sdk:DataGridColumnHeadersPresenter x:Name="ColumnHeadersPresenter" Grid.Column="1"/>
<sdk:DataGridColumnHeader x:Name="TopRightCornerHeader" Grid.Column="2" Template="{StaticResource TopRightHeaderTemplate}"/>
<Rectangle x:Name="ColumnHeadersAndRowsSeparator" Grid.ColumnSpan="3" Fill="#FFC9CACA" Height="1" StrokeThickness="1" VerticalAlignment="Bottom" Width="Auto"/>
<sdk:DataGridRowsPresenter x:Name="RowsPresenter" Grid.ColumnSpan="2" Grid.Row="1"/>
<Rectangle x:Name="BottomRightCorner" Grid.Column="2" Fill="#FFE9EEF4" Grid.Row="2"/>
<Rectangle x:Name="BottomLeftCorner" Grid.ColumnSpan="2" Fill="#FFE9EEF4" Grid.Row="2"/>
<ScrollBar x:Name="VerticalScrollbar" Grid.Column="2" Margin="0,-1,-1,-1" Orientation="Vertical" Grid.Row="1" Width="18"/>
<Grid Grid.Column="1" Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle x:Name="FrozenColumnScrollBarSpacer"/>
<ScrollBar x:Name="HorizontalScrollbar" Grid.Column="1" Height="18" Margin="-1,0,-1,-1" Orientation="Horizontal"/>
</Grid>
<sdk:ValidationSummary x:Name="ValidationSummary" Grid.ColumnSpan="3" MaxHeight="90" Grid.Row="3"/>
</Grid>
</Border>
<Border x:Name="DisabledVisualElement" Background="#8CFFFFFF" CornerRadius="2" HorizontalAlignment="Stretch" Height="Auto" IsHitTestVisible="False" Opacity="0" VerticalAlignment="Stretch" Width="Auto"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SLDataGridColumnHeaderStyle" TargetType="sdk:DataGridColumnHeader">
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="SeparatorBrush" Value="#FFC9CACA"/>
<Setter Property="Padding" Value="4"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGridColumnHeader">
<StackPanel x:Name="Root">
<VisualStateManager.CustomVisualStateManager>
<ei:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates" ei:ExtendedVisualStateManager.UseFluidLayout="True">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="#FF448DCA" Storyboard.TargetProperty="(Fill).Color" Storyboard.TargetName="BackgroundRectangle"/>
<ColorAnimation Duration="0" To="#7FFFFFFF" Storyboard.TargetProperty="(Fill).(GradientStops)[3].Color" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#CCFFFFFF" Storyboard.TargetProperty="(Fill).(GradientStops)[2].Color" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#F2FFFFFF" Storyboard.TargetProperty="(Fill).(GradientStops)[1].Color" Storyboard.TargetName="BackgroundGradient"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" To="#FF448DCA" Storyboard.TargetProperty="(Fill).Color" Storyboard.TargetName="BackgroundRectangle"/>
<ColorAnimation Duration="0" To="#D8FFFFFF" Storyboard.TargetProperty="(Fill).(GradientStops)[0].Color" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#C6FFFFFF" Storyboard.TargetProperty="(Fill).(GradientStops)[1].Color" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#8CFFFFFF" Storyboard.TargetProperty="(Fill).(GradientStops)[2].Color" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#3FFFFFFF" Storyboard.TargetProperty="(Fill).(GradientStops)[3].Color" Storyboard.TargetName="BackgroundGradient"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SortStates" ei:ExtendedVisualStateManager.UseFluidLayout="True">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Unsorted"/>
<VisualState x:Name="SortAscending">
<Storyboard>
<DoubleAnimation Duration="0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SortIcon"/>
</Storyboard>
</VisualState>
<VisualState x:Name="SortDescending">
<Storyboard>
<DoubleAnimation Duration="0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SortIcon"/>
<DoubleAnimation Duration="0" To="-.9" Storyboard.TargetProperty="(RenderTransform).ScaleY" Storyboard.TargetName="SortIcon"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Height="24" Width="147">
<Rectangle x:Name="BackgroundRectangle" Fill="#FF1F3B53" Stretch="Fill" Margin="0,0,-1,0"/>
<Rectangle x:Name="BackgroundGradient" Stretch="Fill" Margin="0,0,-1,0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
<GradientStop Color="#FCFFFFFF" Offset="0.015"/>
<GradientStop Color="#F7FFFFFF" Offset="0.375"/>
<GradientStop Color="#E5FFFFFF" Offset="0.6"/>
<GradientStop Color="#D1FFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Grid HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="4,4,0,4" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding Content}"/>
<Path x:Name="SortIcon" Grid.Column="1" Data="F1 M -5.215,6.099L 5.215,6.099L 0,0L -5.215,6.099 Z " Fill="#FF444444" HorizontalAlignment="Left" Margin="4,0,0,0" Opacity="0" RenderTransformOrigin=".5,.5" Stretch="Uniform" VerticalAlignment="Center" Width="8">
<Path.RenderTransform>
<ScaleTransform ScaleY=".9" ScaleX=".9"/>
</Path.RenderTransform>
</Path>
</Grid>
<Rectangle x:Name="VerticalSeparator" Fill="{TemplateBinding SeparatorBrush}" Visibility="{TemplateBinding SeparatorVisibility}" VerticalAlignment="Stretch" Width="1" HorizontalAlignment="Right" Margin="0,0,-1,0" d:LayoutOverrides="Width"/>
</Grid>
<Grid Height="24" Background="#FFE4E4E4">
<TextBox TextWrapping="Wrap" Text="TextBox" d:LayoutOverrides="Width"/>
</Grid>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</sdk:DataGrid.Resources>
<sdk:DataGrid.Style>
<StaticResource ResourceKey="SLDataGridStyle"/>
</sdk:DataGrid.Style>
<sdk:DataGrid.ColumnHeaderStyle>
<StaticResource ResourceKey="SLDataGridColumnHeaderStyle"/>
</sdk:DataGrid.ColumnHeaderStyle>
It is possible to add custom controls to the headers of a Silverlight DataGrid, but it's not obvious how to do so, and it is a bit of a pain.
There are two things you need to do:
Specify the controls you want to add to the column header by applying a ContentTemplate to the HeaderStyle of the column header. For this to work, you'll need the following two XAML namespace declarations:
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:dataprimitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data"
<sdk:DataGridTemplateColumn Binding="...">
<sdk:DataGridTemplateColumn.HeaderStyle>
<Style TargetType="dataprimitives:DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=SomeFlag, Mode=TwoWay}" />
<TextBlock Text="Header text" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</sdk:DataGridTemplateColumn.HeaderStyle>
<!-- other DataGridTemplateColumn stuff -->
<sdk:DataGridTemplateColumn>
In this example, I've used a CheckBox with an IsChecked property bound to a view-model property SomeFlag, and a TextBlock. I used a DataGridTemplateColumn in this example, but this approach should also work with DataGridTextColumn and DataGridCheckBoxColumn provided you replace sdk:DataGridTemplateColumn.HeaderStyle with sdk:DataGridTextColumn.HeaderStyle and similarly for DataGridCheckBoxColumn.
If you only want to add static content to the column header, there's nothing more you need to do. However, if you wish to use data-binding, you need a further step, as otherwise the data-context of the controls in the header will not be set correctly. This requires a bit of code-behind.
The following methods search through the visual tree for ContentPresenters within DataGridColumnHeaders and set the DataContexts of these ContentPresenters:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
/// <summary>
/// Sets the DataContext of each column header within the given data-grid.
/// </summary>
/// <param name="dataGrid">The DataGrid.</param>
/// <param name="dataContext">The data-context to set.</param>
public static void SetHeaderDataContexts(DataGrid dataGrid, object dataContext)
{
// First we look for a DataGridColumnHeadersPresenter.
DataGridColumnHeadersPresenter colsPresenter = GetObjectOfType<DataGridColumnHeadersPresenter>(dataGrid);
if (colsPresenter == null)
{
return;
}
// The ColumnHeadersPresenter contains all of the column headers as
// direct children. Within each column header is a ContentPresenter,
// whose DataContext will normally be null. For each ContentPresenter
// found, set its DataContext to be that given.
int colHeaderCount = VisualTreeHelper.GetChildrenCount(colsPresenter);
for (int i = 0; i < colHeaderCount; ++i)
{
var header = VisualTreeHelper.GetChild(colsPresenter, i) as DataGridColumnHeader;
if (header != null)
{
ContentPresenter contentPresenter = GetObjectOfType<ContentPresenter>(header);
if (contentPresenter != null)
{
contentPresenter.DataContext = dataContext;
}
}
}
}
/// <summary>
/// Returns the first descendant object of the given parent object within
/// the visual tree that is an instance of the specified type.
/// </summary>
/// <remarks>
/// The visual tree is searched in a depth-first manner, and the first
/// object of type <c>TObject</c> found within the tree is returned. If no
/// control of this type is found, <c>null</c> is returned instead.
/// </remarks>
/// <typeparam name="TObject">The type of object to search for. This must
/// be a subclass of <see cref="DependencyObject"/>.</typeparam>
/// <param name="parent">The parent control to search within.</param>
/// <returns>
/// The first control of the specified type found, or <c>null</c> if none
/// were found.
/// </returns>
public static TObject GetObjectOfType<TObject>(DependencyObject parent) where TObject : DependencyObject
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; ++i)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is TObject)
{
return child as TObject;
}
else
{
TObject obj = GetObjectOfType<TObject>(child);
if (obj != null)
{
return obj;
}
}
}
return null;
}
The only thing that remains to be done is to call SetHeaderDataContexts. I found that calling it from the user-control constructor didn't work, nor did calling it from the Loaded event (in both cases it had no effect). Calling it from the LayoutUpdated event of the grid really didn't work, as that caused an exception to be thrown.
However, calling it within the constructor by using
Dispatcher.BeginInvoke(() => SetHeaderDataContexts(theDataGrid, this.DataContext));
did appear to work.
Acknowledgements: the idea of setting the ContentTemplate comes from Lars Holm Jensen's answer to a similar question, and the idea of searching through the visual tree comes from a blog post from Manas Patnaik. Both links were found via a similar question.
Luke's answer is excellent.
However, I found that when I put a ComboBox into the header template, the binding (set in code-behind from part (2) of Luke's answer) disappeared after an item in the Combo was selected, or when the column is resized. This is because the column header is being recreated when the column resizes, so the binding gets lost.
I fixed it by setting the binding instead like this -
XAML -
<DataTemplate>
<StackPanel Orientation="Horizontal" Loaded="HeaderTemplate_OnLoaded" >
<CheckBox IsChecked="{Binding Path=SomeFlag, Mode=TwoWay}" />
<TextBlock Text="Header text" />
</StackPanel>
</DataTemplate>
Code-behind -
private void HeaderTemplate_OnLoaded(object sender, RoutedEventArgs e)
{
((FrameworkElement)sender).DataContext = this.DataContext;
}
This worked for me without problems every time.
The column header's style can indeed be changed. I was trying to center the header text & this link's technique worked for me: Silverlight DataGrid Header Horizontal Alignment
I have a scrollviewer and I want to animate the way the vertical scrollbar appears. The scrollbar is set to AUTO , so I want it to fade in when needed and fade out when not needed.
I know how to drill into templates and change colors and appearance, but can I make a change like this ?
This was a fun question. Since Scrollbar and ScrollViewer are sealed this was a bit of a challenge. (I thought of making a copy of ScrollViewer using Reflector, but here is a XAML-only solution).
When I heard animation, I thought states. It would have been nice if ScrollViewer was implemented using states, but unfortunately, it was not. By using DataStateBehavior, we can create states out of a property -- in this case, states for the ComputedVerticalScrollBarVisibility property. For some reason, it didn't work to bind the DataStateBehavior to the ScrollViewer's ComputedVerticalScrollBarVisibility using TemplateBinding. (Anyone know why?) I was able to bind it to the VerticalScrollbar Visibility property, but I decided not to:
In order for the Fade out to work, I didn't want the VerticalScrollbar.Visibility to still be bound to ComputedVerticalScrollBarVisibility because if it was, the scrollbar would immediately disapper when the property changed. Instead, I used the VerticalScrollbar Tag property to hold the ComputedVerticalScrollBarVisibility and bound the DataStateBehavior to the VerticalScrollbar Tag.
Now that states are in place, it was an easy matter to set the Opacity for each state and the state transition duration and, voila!, you have a fade in ScrollViewer.
<UserControl
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:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="SilverlightApplication5.MainPage"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<Style x:Key="ScrollViewerStyle1" TargetType="ScrollViewer">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="VerticalScrollBarVisibility" Value="Visible"/>
<Setter Property="Padding" Value="4"/>
<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="ScrollViewer">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="VerticalVisible">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="VerticalScrollBar" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="VerticleHidden">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="VerticalScrollBar" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="{TemplateBinding Background}">
<i:Interaction.Behaviors>
<ei:DataStateBehavior Binding="{Binding Tag, ElementName=VerticalScrollBar}" Value="Visible" TrueState="VerticalVisible" FalseState="VerticleHidden"/>
</i:Interaction.Behaviors>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollContentPresenter x:Name="ScrollContentPresenter" Cursor="{TemplateBinding Cursor}" ContentTemplate="{TemplateBinding ContentTemplate}" Margin="{TemplateBinding Padding}"/>
<Rectangle Grid.Column="1" Fill="#FFE9EEF4" Grid.Row="1"/>
<ScrollBar x:Name="VerticalScrollBar" Grid.Column="1" IsTabStop="False" Maximum="{TemplateBinding ScrollableHeight}" Margin="0,-1,-1,-1" Minimum="0" Orientation="Vertical" Grid.Row="0" Tag="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{TemplateBinding VerticalOffset}" ViewportSize="{TemplateBinding ViewportHeight}" Width="18"/>
<ScrollBar x:Name="HorizontalScrollBar" Grid.Column="0" Height="18" IsTabStop="False" Maximum="{TemplateBinding ScrollableWidth}" Margin="-1,0,-1,-1" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{TemplateBinding HorizontalOffset}" ViewportSize="{TemplateBinding ViewportWidth}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="Beige">
<ScrollViewer VerticalScrollBarVisibility="Auto" Style="{StaticResource ScrollViewerStyle1}">
<Rectangle Margin="10" Fill="LightBlue" MinHeight="300" />
</ScrollViewer>
</Grid>
</UserControl>
To see this in action, run this code and shrink the browser window. The scrollbar will fade into view.
I'm trying to achieve the effect of a pop-up when the user right-clicks in a Silverlight application that shows essentially a custom control. I'm using a Context Menu, and all is working great except that I'm having trouble styling the context menu so that it doesn't highlight itself when the user mouses over.
Here's a snippet of what I'm trying to do:
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu Height="100" Background="Transparent" HorizontalOffset="-100" VerticalOffset="-100" Margin="98,112,0,0" Name="contextMenu1" VerticalAlignment="Top" Width="200">
<toolkit:ContextMenu.Style>
<Style TargetType="toolkit:ContextMenu">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:ContextMenu">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="2">
<Grid>
<ItemsPresenter Margin="{TemplateBinding Padding}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</toolkit:ContextMenu.Style>
<Canvas Width="100" Height="100" Background="Transparent">
<Button Width="100" Height="30">Something</Button>
<Button Width="100" Height="30" Canvas.Top="70">Something Else</Button>
</Canvas>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
When the menu is visible I get the effect I want (the two buttons just floating near the mouse), but when I mouse over it the entire box of the context menu highlights itself.
Here's a sample app that demonstrates this:
http://github.com/vermeeca/ContextMenuDemo
How can I disable that effect?
Thanks to a co-worker I've got the solution. I just had to set the ItemContainerStyle on the ContextMenu.
<UserControl.Resources>
<Style x:Key="NoMouseOverStyle" TargetType="toolkit:MenuItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="4,3,2,3"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:MenuItem">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="0.5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Presenter"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Unfocused"/>
<!-- VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Bg"/>
<ColorAnimation Duration="0" To="#40FFFFFF" Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)" Storyboard.TargetName="InnerBorder"/>
</Storyboard>
</VisualState -->
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle Fill="{TemplateBinding Background}" RadiusY="2" RadiusX="2" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="1"/>
<Rectangle x:Name="Bg" Opacity="0" RadiusY="2" RadiusX="2" Stroke="#8071CBF1" StrokeThickness="1">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#34C5EBFF" Offset="0"/>
<GradientStop Color="#3481D8FF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="InnerBorder" Margin="1" RadiusY="2" RadiusX="2" Stroke="Transparent"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="24" Width="Auto"/>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="17"/>
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding Icon}" Margin="1" VerticalAlignment="Center"/>
<ContentPresenter x:Name="Presenter" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.Column="2" Margin="{TemplateBinding Padding}"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
And then
<toolkit:ContextMenu Height="100" Background="Transparent" HorizontalOffset="-100" VerticalOffset="-100" Margin="98,112,0,0" Name="contextMenu1" VerticalAlignment="Top" Width="200" ItemContainerStyle="{StaticResource NoMouseOverStyle}">
Here's one for all you XAML wizards: The WPF Toolkit Calendar control (June 2009) appears to have a bug. The bug only crops up when you modify the ControlTemplate for the calendar, specifically, the PART_CalendarItem.
At the end of this message, I have included the XAML for a (Blend 3.0) window that declares a Calendar and assigns it a ControlTemplate. The control template is an unmodified copy of the Calendar control template, which I got by editing a copy of the control template (in Blend) for the Calendar control and the PART_CalendarItem control.
In line 78 of the XAML (Marked with a comment "EXCEPTION" below), the VisualStateManager assigns a TextColor to a mouse-over on the Month header of the control. However, in the control template the text color is assigned to the Grid that holds the Month button, rather than the month button itself. That causes an exception in both VS2008 and Blend 3.0 when a calendar is assigned the unmodified control template, as in the XAML below.
I can't quite figure out how to modify the control template to eliminate the bug, short of removing the mouse-over highlighting. I'd like to keep it, but I don't see what the TextColor property should target. Any suggestions? Thanks for your help!
XAML Markup
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Custom="http://schemas.microsoft.com/wpf/2008/toolkit"
x:Class="WpfApplication1.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<Style x:Key="CalendarStyle1" TargetType="{x:Type Custom:Calendar}">
<Setter Property="Foreground" Value="#FF333333"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFE4EAF0" Offset="0"/>
<GradientStop Color="#FFECF0F4" Offset="0.16"/>
<GradientStop Color="#FFFCFCFD" Offset="0.16"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<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="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Custom:Calendar}">
<StackPanel x:Name="PART_Root" HorizontalAlignment="Center">
<Custom:CalendarItem x:Name="PART_CalendarItem" Style="{DynamicResource CalendarItemStyle1}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CalendarItemStyle1" TargetType="{x:Type Custom:CalendarItem}">
<Setter Property="Margin" Value="0,3"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Custom:CalendarItem}">
<ControlTemplate.Resources>
<DataTemplate x:Key="DayTitleTemplate">
<TextBlock HorizontalAlignment="Center" Margin="0,6" VerticalAlignment="Center" FontFamily="Verdana" FontSize="9.5" FontWeight="Bold" Foreground="#FF333333" Text="{Binding}"/>
</DataTemplate>
</ControlTemplate.Resources>
<Grid x:Name="PART_Root">
<Grid.Resources>
<SolidColorBrush x:Key="DisabledColor" Color="#A5FFFFFF"/>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="00:00:00" Storyboard.TargetName="PART_DisabledVisual" Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1">
<Border BorderBrush="White" BorderThickness="2" CornerRadius="1">
<Grid>
<Grid.Resources>
<ControlTemplate x:Key="HeaderButtonTemplate" TargetType="{x:Type Button}">
<Grid Cursor="Hand">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Color" To="#FF73A9D8"/> <!-- EXCEPTION -->
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="00:00:00" Storyboard.TargetName="buttonContent" Storyboard.TargetProperty="Opacity" To="0.5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="buttonContent" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="1,4,1,9" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" TextElement.Foreground="#FF333333" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="NextButtonTemplate" TargetType="{x:Type Button}">
<Grid Cursor="Hand">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Color" To="#FF73A9D8"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Opacity" To="0.5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle Fill="#11E5EBF1" Stretch="Fill" Opacity="1"/>
<Grid>
<Path Fill="#FF333333" Stretch="Fill" HorizontalAlignment="Right" Margin="0,-6,14,0" VerticalAlignment="Center" Width="6" Height="10" Data="M282.875,231.875L282.875,240.375 288.625,236z"/>
</Grid>
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="PreviousButtonTemplate" TargetType="{x:Type Button}">
<Grid Cursor="Hand">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Color" To="#FF73A9D8"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Opacity" To="0.5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle Fill="#11E5EBF1" Stretch="Fill" Opacity="1"/>
<Grid>
<Path Fill="#FF333333" Stretch="Fill" HorizontalAlignment="Left" Margin="14,-6,0,0" VerticalAlignment="Center" Width="6" Height="10" Data="M288.75,232.25L288.75,240.625 283,236.625z"/>
</Grid>
</Grid>
</ControlTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="PART_PreviousButton" HorizontalAlignment="Left" Width="28" Height="20" Focusable="False" Grid.Column="0" Grid.Row="0">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Cursor="Hand">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Color" To="#FF73A9D8"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Opacity" To="0.5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle Fill="#11E5EBF1" Stretch="Fill" Opacity="1"/>
<Grid>
<Path Fill="#FF333333" Stretch="Fill" HorizontalAlignment="Left" Margin="14,-6,0,0" VerticalAlignment="Center" Width="6" Height="10" Data="M288.75,232.25L288.75,240.625 283,236.625z"/>
</Grid>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
<Button x:Name="PART_HeaderButton" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="10.5" FontWeight="Bold" Focusable="False" Grid.Column="1" Grid.Row="0" Template="{DynamicResource ButtonControlTemplate1}"/>
<Button x:Name="PART_NextButton" HorizontalAlignment="Right" Width="28" Height="20" Focusable="False" Grid.Column="2" Grid.Row="0">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Cursor="Hand">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Color" To="#FF73A9D8"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Opacity" To="0.5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle Fill="#11E5EBF1" Stretch="Fill" Opacity="1"/>
<Grid>
<Path Fill="#FF333333" Stretch="Fill" HorizontalAlignment="Right" Margin="0,-6,14,0" VerticalAlignment="Center" Width="6" Height="10" Data="M282.875,231.875L282.875,240.375 288.625,236z"/>
</Grid>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
<Grid x:Name="PART_MonthView" Margin="6,-1,6,6" Visibility="Visible" Grid.ColumnSpan="3" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
</Grid>
<Grid x:Name="PART_YearView" Margin="6,-3,7,6" Visibility="Hidden" Grid.ColumnSpan="3" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
</Grid>
</Grid>
</Border>
</Border>
<Rectangle x:Name="PART_DisabledVisual" Fill="#A5FFFFFF" Stretch="Fill" Stroke="#A5FFFFFF" StrokeThickness="1" RadiusX="2" RadiusY="2" Opacity="0" Visibility="Collapsed"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Visibility" TargetName="PART_DisabledVisual" Value="Visible"/>
</Trigger>
<DataTrigger Binding="{Binding DisplayMode, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type Custom:Calendar}}}" Value="Year">
<Setter Property="Visibility" TargetName="PART_MonthView" Value="Hidden"/>
<Setter Property="Visibility" TargetName="PART_YearView" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding DisplayMode, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type Custom:Calendar}}}" Value="Decade">
<Setter Property="Visibility" TargetName="PART_MonthView" Value="Hidden"/>
<Setter Property="Visibility" TargetName="PART_YearView" Value="Visible"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="ButtonControlTemplate1" TargetType="{x:Type Button}">
<Grid Cursor="Hand">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="00:00:00" Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Color" To="#FF73A9D8"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="00:00:00" Storyboard.TargetName="buttonContent" Storyboard.TargetProperty="Opacity" To="0.5"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="buttonContent" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="1,4,1,9" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" TextElement.Foreground="#FF333333" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</ControlTemplate>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<Custom:Calendar HorizontalAlignment="Left" VerticalAlignment="Top" Style="{DynamicResource CalendarStyle1}"/>
</Grid>
</Window>
We just experienced the same thing at work. This doesn't appear to be a bug in the WPFToolkit, rather there is an issue with Expression Blend which crops up because the people who made the original template got a little tricky.
First, go grab the default template. If you download the source they will be in Toolkit-Release/Calendar/Themes/Generic.xaml. The source can be found on the WPF Toolkit CodePlex site.
http://wpf.codeplex.com/
The CalendarItemTemplate has this sort of a setup:
<Style TargetType="primitives:CalendarItem">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="primitives:CalendarItem">
...
<Grid Name="PART_Root" >
<Border
...
<Border CornerRadius="1" BorderBrush="#FFFFFFFF" BorderThickness="2">
<Grid>
<Grid.Resources>
<ControlTemplate x:Key="HeaderButtonTemplate" TargetType="Button">
...
<Button x:Name="PART_HeaderButton" Template="{StaticResource HeaderButtonTemplate}"
...
This is the original HeaderButtonTemplate:
<ControlTemplate x:Key="HeaderButtonTemplate" TargetType="Button">
<Grid Cursor="Hand">
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="Normal" />
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Color" To="#FF73A9D8" Duration="0" />
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="buttonContent" Storyboard.TargetProperty="Opacity" To=".5" Duration="0" />
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<ContentPresenter
x:Name="buttonContent"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="1,4,1,9"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<TextElement.Foreground>
<SolidColorBrush x:Name="TextColor" Color="#FF333333"/>
</TextElement.Foreground>
</ContentPresenter>
</Grid>
</ControlTemplate>
The part that concerns us is here:
<ContentPresenter
x:Name="buttonContent"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="1,4,1,9"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<TextElement.Foreground>
<SolidColorBrush x:Name="TextColor" Color="#FF333333"/>
</TextElement.Foreground>
</ContentPresenter>
Notice the TextElement attached property setter that instantiates the SolidColorBrush. This is the named brush that is targeted by the storyboards.
When you do the "Edit Copy of Template" thing in Blend, it will inline some of the templates so that the Header button template will be set directly instead of being contained in the grid resources.
<Button x:Name="PART_HeaderButton" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="10.5" FontWeight="Bold" Focusable="False" Grid.Column="1" Grid.Row="0">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Cursor="Hand">
I don't know why it does this, when I edit a copy of a template I'm expecting an actual copy of the template. I suppose I understand that sometimes a template is referenced from outside, but in this case it's not - and even if it is it seems more prudent to copy it in its entirety and add it to the style/controltemplate resources. What is worse, as part of the reprocessing Blend modifies the contentpresenter definition in the template, turning it into this:
<ContentPresenter x:Name="buttonContent"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="1,4,1,9"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
TextElement.Foreground="#FF333333" />
So, in other words no more named brush, and the storyboard target is now incorrect.
Fortunately the fix is easy - use the original template as your starting point. Trouble is, blend doesn't like it and won't display because for some reason it can only set this attached property on the contentpresenter as part of the opening tag, not in the expanded mode or whatever it's called. Of course, it's probably quite possible to duplicate the functionality in another manner that is more blendable.
EDIT: Here is a quick way to hack up the template to make it blendable. And it really is a hack, though mostly a harmless one. I don't advocate doing things like this normally, but it does seem to work fine.
<ControlTemplate x:Key="HeaderButtonTemplate" TargetType="Button">
<Grid Cursor="Hand">
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="Normal" />
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="TextColor" Storyboard.TargetProperty="Color" To="#FF73A9D8" Duration="0" />
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="buttonContent" Storyboard.TargetProperty="Opacity" To=".5" Duration="0" />
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<!-- A dummy Rectangle that is essentially a container for the TextColor brush -->
<Rectangle Width="0" Height="0">
<Rectangle.Fill>
<SolidColorBrush x:Name="TextColor" Color="#FF333333"/>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter
x:Name="buttonContent"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="1,4,1,9"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextElement.Foreground="{Binding ElementName=TextColor}">
</ContentPresenter>
</Grid>
</ControlTemplate>
The essense of it is to house the brush as part of another object - technically visible if too small to be shown, and then do a binding on the contentpresenter - because it's done in the opening tag Blend doesn't complain. Yeah I know, this sort of smells, but it's the smallest rewrite of the original template that I can see to make it work.
Is it possible to update a templated AutoCompleteBox's BorderBrush at runtime? I can't seem to set the BorderBrush or the background.
Even base statements like TxtFoodSearch.BorderBrush = new SolidColorBrush(Colors.Red) don't seem to made a difference after the page has loaded.
My Xaml is below.
<controls:AutoCompleteBox x:Name="MyAutoCompleteSample" Margin="17,24,58,32" FontSize="12">
<controls:AutoCompleteBox.Style>
<Style TargetType="controls:AutoCompleteBox">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:AutoCompleteBox">
<Grid Margin="{TemplateBinding Padding}"
Background="{TemplateBinding Background}">
<TextBox IsTabStop="True" x:Name="Text" Style="{TemplateBinding TextBoxStyle}" Margin="0"
KeyDown="MyAutoCompleteSample_KeyDown"
/>
<Popup x:Name="Popup">
<Border x:Name="PopupBorder" HorizontalAlignment="Stretch" Opacity="0.0" BorderThickness="0" CornerRadius="3">
<Border.RenderTransform>
<TranslateTransform X="1" Y="1" />
</Border.RenderTransform>
<Border.Background>
<SolidColorBrush Color="#11000000" />
</Border.Background>
<Border
HorizontalAlignment="Stretch"
Opacity="1.0"
Padding="0"
ToolTipService.ToolTip="Select or enter your food selection"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="3">
<Border.RenderTransform>
<TransformGroup>
<TranslateTransform X="-1" Y="-1" />
</TransformGroup>
</Border.RenderTransform>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFDDDDDD" Offset="0"/>
<GradientStop Color="#AADDDDDD" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<ListBox
x:Name="SelectionAdapter"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
ItemTemplate="{TemplateBinding ItemTemplate}" />
</Border>
</Border>
</Popup>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PopupStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.1" To="PopupOpened" />
<VisualTransition GeneratedDuration="0:0:0.2" To="PopupClosed" />
</VisualStateGroup.Transitions>
<VisualState x:Name="PopupOpened">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PopupBorder" Storyboard.TargetProperty="Opacity" To="1.0" />
</Storyboard>
</VisualState>
<VisualState x:Name="PopupClosed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PopupBorder" Storyboard.TargetProperty="Opacity" To="0.0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</controls:AutoCompleteBox.Style>
</controls:AutoCompleteBox>
One way I've managed to find how to address the styling through code is the following.
Walk the visual tree and get the AutoCompleteBox, cast that into a textbox, then adjust the colors (border, background, etc)
//Cast into textbox
TextBox Temp = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(MyAutoCompleteControl, 0), 0) as TextBox;
Temp.BorderBrush = new SolidColorBrush(Colors.Red);//Change border color
I'm sure there is a better way, but this seems to work.
If you're using Silverlight 3 (where styles can be set multiple times), then it is easier: you can actually set the TextBoxStyle (on MSDN here).
You can then create a new Style in code-behind (a pain), or perhaps change/apply another of your pre-defined styles in code.