storyboard access element in a control template - silverlight

I have a usercontrol that contains a custom styled button that I wish to animate.
<UserControl>
<!-- omitted namespaces etc -->
<UserControl.Resources>
<Style x:Key="myButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse x:Name="ellipse" Fill="Orange" />
<es:Arc x:Name="arc" EndAngle="360" Fill="Red" StartAngle="360"/>
</Grid>
</ControlTemplate TargetType="Button">
</Setter.Value>
</Setter>
</Style>
</UserControl.Resouces>
<Grid x:Name="LayoutRoot" />
<Button Tap="Fire_Animation" x:Name="myButton" Style="{StaticResource myButtonStyle}" />
</Grid>
</UserControl>
Once the Button is Tapped, the Fire_Animation method starts a storyboard which is supposed to modify the "Arc" element inside the button's template.
I've seen examples for WPF like this:
// .. previous necessary method calls
StoryBoard.SetTargetName(_myAnimation, "arc");
_storyboard.Begin(myButton, myButton.Template);
But there's no such 'Begin' overload in Windows Phone and as such my storyboard raises an exception that it can't find the 'arc' element. Is there any other workaround?

I would recommend that when you tap the button, that it sets a visual state. You can then provide a storyboard as part of your button template that animates the arc element when the given visual state is applied.

Related

Can't set both ContentTemplateSelector and Template properties on a DataGridColumnHeader

In short, the question title says it all. For those that want more detail, here is the crux of my problem: I need to apply a custom ControlTemplate to the DataGridColumnHeader elements in my DataGrid control, but I also need to style them differently, depending on the cell data nearest the header. However, when I set both the ContentTemplateSelector and Template properties on a DataGridColumnHeader element, the DataTemplateSelector that is set as the value of the ContentTemplateSelector property is not called. Commenting out the Template property setting confirms this to be the case, as the DataTemplateSelector element will now be called.
Yes, I know that you guys love to see some code, but I have completely templated the whole DataGrid control to look like Excel, so as you can imagine, I have far too much code to display here. But just to please you code hungry devs, I've recreated my problem in a much simpler example... let's first see the XAML:
<Window x:Class="WpfApp1.MainWindow"
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:Local="clr-namespace:WpfApp1"
xmlns:System="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<DataGrid.Items>
<System:String>One</System:String>
<System:String>Two</System:String>
<System:String>Three</System:String>
</DataGrid.Items>
<DataGrid.Resources>
<Local:StringDataTemplateSelector x:Key="StringDataTemplateSelector" />
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
<Setter Property="ContentTemplateSelector" Value="{StaticResource StringDataTemplateSelector}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" />
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
</DataGrid>
</Grid>
</Window>
Now the most simple DataTemplateSelector class:
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
public class StringDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
Debugger.Break();
return null;
}
}
}
In the XAML, we see a DataGrid, with just one DataGridTemplateColumn and three string values, one on each row, and some resources. There is a Style for the DataGridColumnHeader element in the Resource section, with the most simple ControlTemplate set up for it, that only includes the required named parts from the default ControlTemplate.
If you run the application as it is, then it will NOT currently break at the Debugger.Break() method in the StringDataTemplateSelector class. This is unexpected. If you now comment out the setting of the Template property in the Style and run the application again, then you will now see that program execution will now break at the Debugger.Break() method, as expected.
Further information:
In the Remarks section of the ContentControl.ContentTemplateSelector Property page of MSDN, it states that
If both the ContentTemplateSelector and the ContentTemplate properties are set, then this property is ignored.
However, it does not mention the Template property and there is also no mention of this on the Control.Template Property page on MSDN.
Furthermore, I tried this same setup using a simple Button control and can confirm that setting both the ContentTemplateSelector and the ContentTemplate properties on that does NOT stop the StringDataTemplateSelector class from being called:
<ItemsControl>
<ItemsControl.Resources>
<Local:StringDataTemplateSelector x:Key="StringDataTemplateSelector" />
<Style TargetType="{x:Type Button}">
<Setter Property="ContentTemplateSelector" Value="{StaticResource StringDataTemplateSelector}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Ellipse Stroke="Red" StrokeThickness="1" Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding Height}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.Resources>
<Button Content="One" />
<Button Content="Two" />
<Button Content="Three" />
</ItemsControl>
So, what I'm after is a way to apply a custom ControlTemplate element to the DataGridColumnHeader objects, yet still be able to have the DataTemplateSelector class called during the rendering process.
add a content presenter in your controltemplate?
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" />
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" />
<ContentPresenter></ContentPresenter>
</Grid>
</ControlTemplate>

Binding ContentPresenter.Content to TemplatedParent (WPF/Silverlight)

Basically, I would like to overlay, for example: TextBlock over Button, by using ControlTemplate (applied to this Button), but I don't want to get rid of default template of it.
Example:
<Grid Grid.Row="1" Grid.ColumnSpan="2">
<Grid.Resources>
<Style x:Key="myStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<ContentPresenter />
<TextBlock Text="textBlock"
Margin="10" Foreground="Red"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Button Style="{StaticResource myStyle}" Content="button1"></Button>
</Grid>
and it gives Button stripped of it's default template:
Rather, I would like to receive something like this:
Is it possible by using ControlTemplate? I was trying to bind TemplatedParent to ContentPresenter.Content like here:
<ContentPresenter Content="{Binding
RelativeSource={RelativeSource Mode=TemplatedParent},
Path=.,
Mode=TwoWay}"/>
or other combinations, but I couldn't make it work.
Edit:
Because I would like to be able to apply this TextBlock not only to a button (it was just an example) but to any Control, I don't want do it by copying default style (to the resources or somewhere), for every Control.
Also, I would prefer not to create UserControl, because I would like to keep xaml clean as much as possible (I mean with system Controls) - and just to turn on/off the overlaying TextBlock by using a ControlTemplate.
You could add the default style on the button and modify it to add your TextBlock. The second option, my preference, is to create a new UserControl that will contain the Button and the TextBlock with IsHitTestVisible=False. You can then add dependency properties to be able to bind to the button and the text block.

Reset Style in certain portion of Visual Tree in WPF

I am setting some global styles for TextBox, ComboBox, TextBlock, etc. in my App.xaml file. I want these styles to flow down through the visual tree for a consistent look and that is what they are doing.
However, I am using a Ribbon in part of my UI. The style customizations are completely throwing off the appearance of the Ribbon. The ribbon sits at the same level as many other UI elements so is there a way to just reset the style for the ribbon and its visual children
I don't think that you can change this wpf behaviour.
But you can try to contain all global styles to specific resource dictionary and use it in all other VisualTree elements.
Or you can try something like this:
<Window ...>
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
<DockPanel LastChildFill="True">
<Button x:Name="button1" Content="button" DockPanel.Dock="Top" />
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Button">
</Style>
</StackPanel.Resources>
<Button x:Name="button2" Content="lala" />
</StackPanel>
</DockPanel>
</Window>
Element with name "button2" will be default.

Control Template for a button to be displayed as an image.png

Iam have been working on the control templates since few days,iam successfull in changing a button to the ellipse ,but when iam about to create a control template for button to be displyed as a image,i am not Successful.If any one can know it ,please help me out.
The following xaml shows a button with a ControlTemplate consisting of only an image:
<Button>
<Button.Template>
<ControlTemplate>
<Image Source="/arrow_down_blue.png" Stretch="None" />
</ControlTemplate>
</Button.Template>
</Button>
If you cannot get it to work, make sure that the path to your image is valid. The easiest way is to add the image to your solution and mark it as Resource, by right clicking the image in the solution explorer and setting Build Action to Resource. You can then reference the image by using a so called pack URI on the form:
/FolderName/OtherFolderName/FileName.png
The path above is relative to the root of the current project.
The ControlTemplate could also be set though a Style or by setting the Template property of the button to a StaticResource:
<Grid>
<Grid.Resources>
<ControlTemplate x:Key="ImageButtonTemplate">
<Image Source="/arrow_down_blue.png" Stretch="None" />
</ControlTemplate>
<Style TargetType="Button" x:Key="ImageButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Image Source="/arrow_down_blue.png" Stretch="None" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<StackPanel>
<Button Template="{StaticResource ImageButtonTemplate}" />
<Button Style="{StaticResource ImageButtonStyle}" />
</StackPanel>
</Grid>
An example of how to add triggers to your control template can be found in this question.

WPF UserControl validation problem

I have UserControl bounded to my view model. View model implements IDataErrorInfo. UserConrol has Validation.ErrorTemplate. In this template I use converter to show tooltip with errors:
<UserControl.Style>
<Style TargetType="{x:Type UserControl}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<AdornedElementPlaceholder x:Name="adorner">
<Image x:Name="imgError"
Width="32"
Height="32"
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
ToolTip="{Binding ElementName=adorner,Path=AdornedElement.(Validation.Errors),Converter={StaticResource ValidationErrors2TooltipConverter},ConverterParameter='Couldn't save hour work:'}"
Source="{StaticResource ErrorDrawingImage}" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Style>
When I change some property (for instance: ComboBox's selection), the number of error should change, but it doesn't. I couldn't find a way to refresh errors in ToolTip.
Questions:
How could I refresh errors in ToolTip.
Validation works fine for UserControl, but doesn't work for components inside it. I defined Validation.ErrorTemplate's for components in UserControl, but they are not visible, however controls bounded to view models (with IDataErrorInfo).
The validation pattern must be applied for each control inside your UserControl. There's no "inheritance".

Resources