Below given code is used for toggling images. It works but when I click on button white rectangle is shown as a foreground of button. Is there any better way?
private void music_click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("music clickedddd");
switch (key)
{
case 1:
var brush = new ImageBrush();
BitmapImage image = new BitmapImage(new Uri(#"Images/music pause button.png", UriKind.Relative));
brush.ImageSource = image;
music.Background = brush;
key = 0;
System.Diagnostics.Debug.WriteLine("music clickedddd pause");
break;
case 0:
var brush2 = new ImageBrush();
BitmapImage image2 = new BitmapImage(new Uri(#"Images/Music on.png", UriKind.Relative));
brush2.ImageSource = image1;
music.Background = brush2;
key = 1;
System.Diagnostics.Debug.WriteLine("music clickedddd play");
break;
}
}
I recommend styling your ToggleButton to show two different VisualStates for the two cases "paused" and "running" (The ToggleButton control supports the two VisualStates "Checked" and "Unchecked").
How would I do this?
Well I tried the following code and it works:
<UserControl
x:Class="SilverlightApplication2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<ControlTemplate x:Key="MySpecialToggleButton" TargetType="ToggleButton">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="RunningIcon">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="PausedIcon">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image x:Name="PausedIcon" Source="/SilverlightApplication2;component/assets/paused.png" Visibility="Visible" Width="16" Height="16"/>
<Image x:Name="RunningIcon" Source="/SilverlightApplication2;component/assets/running.png" Visibility="Collapsed" Width="16" Height="16"/>
</Grid>
</ControlTemplate>
</UserControl.Resources>
<ToggleButton Height="20" Width="20" Template="{StaticResource MySpecialToggleButton}"/>
I assume you still want to handle the toggling to start playing music or stop it, well you can still handle the click in code behind but you won't have to change the button appearance anymore. And you do not have to track whether the button is toggled or not (your variable named "key"), you can always ask your button if it is checked or unchecked. And you do not need to aks it, just use the specialized ToggleButton events "Checked" and "Unchecked".
You should try using StoryBorads (http://msdn.microsoft.com/en-us/library/ms742868(v=vs.110).aspx) for this type of animation.
Related
I want to change the default text style (foreground color, font weight, etc) for pivot item header text when the header is selected.
E.g., if I have the following:
<Pivot>
<PivotItem Header="One"></PivotItem>
<PivotItem Header="Two"></PivotItem>
</Pivot>
I want the selected pivot item to be bolded when selected and/or change the foreground color (or maybe put the text in a border, etc). I don't want to change the default style for the unselected items.
Thanx,
The XAML framework offers many ways to customize the appearance of your apps. Styles let you set control properties and reuse those settings for a consistent appearance across multiple controls. You create a control template when you want to customize a control's visual structure and visual behavior.
You don't need to put the text of pivot header in a border, edit the Style for PivotHeaderItem would be a good choice, and you can add this style to the Resources of the Page.
Resources are typically definitions of some object that you expect to use more than once.
There is a default PivotHeaderItem styles and templates, you can copy it and add this to you page resources just like this:
<Page
x:Class="..."
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"
mc:Ignorable="d">
<Page.Resources>
<Style TargetType="PivotHeaderItem">
...
</Style>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
...
</Grid>
</Page>
Now if you want to change the foreground of the text in header when the item is selected, you can edit the <VisualState x:Name="Selected"> like this:
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
If you want to change the text of header to be bold, you can edit above VisualState like this:
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="FontWeight">
<DiscreteObjectKeyFrame KeyTime="0" Value="Bold" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
You can leave other VisualStates as defalut, if you just want to change the style when the item is selected.
In XAML
<Pivot SelectionChanged="Pivot_SelectionChanged">
<PivotItem>
<PivotItem.Header>
<TextBlock Text="One"></TextBlock>
</PivotItem.Header>
</PivotItem>
<PivotItem>
<PivotItem.Header>
<TextBlock Text="Two"></TextBlock>
</PivotItem.Header>
</PivotItem>
</Pivot>
In C#
private void Pivot_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Pivot pivot = sender as Pivot;
PivotItem pivotItemSelected = ((PivotItem) ((Pivot) sender).SelectedItem);
for (int i = 0; i < pivot.Items.Count; i++)
{
PivotItem pivotItem = pivot.Items[i] as PivotItem;
TextBlock tb = pivotItem.Header as TextBlock;
if (pivotItem == pivotItemSelected)
{
//Style
tb.Foreground = new SolidColorBrush(Colors.Blue);
}
else
{
tb.Foreground = new SolidColorBrush(Colors.Black);
}
}
}
I hope this can help you
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="QWERTY.animation"
x:Name="Window"
Title="animation"
Width="640" Height="480">
<Window.Resources>
<Storyboard x:Key="Animation">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.FontSize)" Storyboard.TargetName="btn_1">
<EasingDoubleKeyFrame KeyTime="0" Value="11"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="10.667"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.FontWeight)" Storyboard.TargetName="btn_1">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<FontWeight>Normal</FontWeight>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:0.3">
<DiscreteObjectKeyFrame.Value>
<FontWeight>Bold</FontWeight>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="btn_1">
<EasingColorKeyFrame KeyTime="0" Value="#FFEAF0ED"/>
<EasingColorKeyFrame KeyTime="0:0:0.3" Value="#FF106285"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<Button x:Name="btn_2" Content="B" Height="55" Margin="236,98,0,0" VerticalAlignment="Top" Click="btn_2_Click" HorizontalAlignment="Left" Width="72" />
<Button x:Name="btn_1" Content="A" Height="55" Margin="115,98,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="72" Click="btn_1_Click">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#FFEAF0ED" Offset="0.9"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<Button Content="Remove" HorizontalAlignment="Left" Margin="173,179,0,217" Width="75" Click="Button_Click" />
</Grid>
The design will be like below
public partial class animation : Window
{
Storyboard SB;
public animation()
{
this.InitializeComponent();
}
public void Animate(string name)
{
SB = (Storyboard)(FindResource("Animation"));
Storyboard.SetTargetName(SB.Children[0], name);
Storyboard.SetTargetName(SB.Children[1], name);
Storyboard.SetTargetName(SB.Children[2], name);
SB.Begin();
}
private void btn_1_Click(object sender, RoutedEventArgs e)
{
Button Btn_1 = (Button)sender;
Animate(btn_1.Name);
}
private void btn_2_Click(object sender, RoutedEventArgs e)
{
Button Btn_2 = (Button)sender;
Animate(Btn_2.Name);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
SB.Remove();
}
}
It's output will be like below
The above result is after i clicked two buttons one by one.Then I clicked the remove button,only the button B animation is removed. But i want to remove button A and button B animation by clicking of remove button.
You can have only one TargetName at a Time assigned to the Storyboard. By using SetTargetName you are Transfering the Target to the new Button. Then when you click remove, you remove the last one you added. Take a look at this Blog its for SilverLight but should apply here. Your only other option would to be to use Style.Triggers and put your animation in the Style.
From above Link:
In this example, it might not be desirable to stop an animation on one rectangle so that the animation can start on another rectangle. Perhaps you want both animations to run at the same time. However, you cannot use the same animation object to run two separate animations at the same time, because there is only one TargetName. This does not mean that you are back to creating a separate Storyboard for every object. Instead, you need one Storyboard for each animation that you want to run concurrently (synchronously).
I have created a HeaderTemplate for my accordions where I want to display a text block on one side of the header and a hyperlink on the right side. The display is working correctly, but the click event is not called when the user clicks, I'm guessing b/c the header itself is trapping the click for expand/contract.
<layoutToolkit:Accordion>
<layoutToolkit:AccordionItem IsSelected="True">
<layoutToolkit:AccordionItem.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="20">
<TextBlock Margin="0,0,700,0">Cancel Postcards</TextBlock>
<HyperlinkButton Content="Next Call" Foreground="Blue" Click="NextCancel_Click" />
</StackPanel>
</DataTemplate>
</layoutToolkit:AccordionItem.HeaderTemplate>
..... more code ....
Is there a way to get the hyperlink to respond to events without practically creating a new control?
Update: It looks like the header sets all child controls to disabled when expanded which is why the link doesnt work. It will work when you collapse that accordionitem. So, the question now is, how do i prevent the hyperlink from being disabled?
Hey Charlie, I just happened to answer this same question for Epic720. You have to change the Locked VisualState.
Interactive items in Silverlight Accordion Header
Here is the LockedStates VisualStateGroup of the AccordionItem which you should alter. I can post the whole style if you need, though it's quite verbose.
<VisualStateGroup x:Name="LockedStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Locked">
<Storyboard>
<!--
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="IsEnabled" Storyboard.TargetName="ExpanderButton">
<DiscreteObjectKeyFrame KeyTime="0" Value="False"/>
</ObjectAnimationUsingKeyFrames>
-->
</Storyboard>
</VisualState>
<VisualState x:Name="Unlocked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="IsEnabled" Storyboard.TargetName="ExpanderButton">
<DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
I would like to have an item's width shrink on a click of a button.
Right now I have two objects basically, when you click the button on objectA, a storyboard starts that rotates it around the x-axis and collapses it. Then it shows objectB by setting it's visibility to visible and rotates it around into view.
All I want to add is setting the width smaller while the storyboard is happening to objectA and objectB and then setting it back to normal at the end of the storyboard.
I tried setting the Thickness but I got a compile-time error complaining that it was readonly.
<ObjectAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="objectA"
Storyboard.TargetProperty="(UIElement.Margin)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Thickness Left="10" Right="10"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
I have a simple layout for now...
Here is my UI XAML:
<StackPanel>
<Border x:Name="objectA" BorderBrush="Blue" BorderThickness="1" Height="100" Width="100">
<StackPanel>
<TextBox Margin="10"></TextBox>
<Button Width="50" x:Name="btn1" Content="Flip" Click="btn1_Click"/>
</StackPanel>
<Border.Projection>
<PlaneProjection RotationX="0"></PlaneProjection>
</Border.Projection>
</Border>
<Border Visibility="Collapsed" x:Name="objectB" BorderBrush="Red" BorderThickness="1" Height="100" Width="100">
<StackPanel>
<TextBox Margin="10"></TextBox>
<Button Width="50" x:Name="btn2" Content="Flip" Click="btn2_Click"/>
</StackPanel>
<Border.Projection>
<PlaneProjection RotationX="90"></PlaneProjection>
</Border.Projection>
</Border>
Here is the storyboard...
<Storyboard x:Name="Storyboardtest">
<DoubleAnimation BeginTime="00:00:00"
Storyboard.TargetName="objectA"
Storyboard.TargetProperty="(UIElement.Projection).(RotationX)"
From="0" To="-90">
</DoubleAnimation>
<ObjectAnimationUsingKeyFrames
BeginTime="00:00:01"
Storyboard.TargetName="objectA"
Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
BeginTime="00:00:01"
Storyboard.TargetName="objectB"
Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation BeginTime="00:00:01"
Storyboard.TargetName="objectB"
Storyboard.TargetProperty="(UIElement.Projection).(RotationX)"
From="90" To="0">
</DoubleAnimation>
</Storyboard>
If it is just the visual width you want to affect, add the following to your storyboard. It will give the appearance of the controls moving into the distance and back as it flips:
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="objectA">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="objectB">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
you will also need to add the following as I used Expression blend to add the animation and it adds any required elements automatically:
<Border x:Name="objectA" BorderBrush="Blue" BorderThickness="1" Height="100" Width="100" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<CompositeTransform/>
</Border.RenderTransform>
[Snip]
<Border Visibility="Collapsed" x:Name="objectB" BorderBrush="Red" BorderThickness="1" Height="100" Width="100" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<CompositeTransform/>
</Border.RenderTransform>
The problem is that both the Width and Margin properties are not DependencyProperties so they can not be animated. On workaround method to accomplish this involves adding some custom DependencyProperties to your user control code-behind which can be hooked up to the storyboard and can in turn manipulate the actual properties of the objects.
For example you could add this DependencyProperty to your UserControl which basically allow the setting of the Width property of object A:
public static readonly DependencyProperty ObjectWidthProperty = DependencyProperty.Register(
"ObjectWidth",
typeof(double),
typeof(MainPage),
new PropertyMetadata(50.0, new PropertyChangedCallback(OnObjectWidthChanged)));
public double ObjectWidth
{
get { return (double)GetValue(ObjectWidthProperty); }
set { SetValue(ObjectWidthProperty, value); }
}
private static void OnObjectWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MainPage)d).OnObjectWidthChanged(e);
}
private void OnObjectWidthChanged(DependencyPropertyChangedEventArgs e)
{
this.objectA.Width = this.ObjectWidth;
}
You could then add the following to your storyboard which would animate the width of objectA from 50 pixels down to 0:
<DoubleAnimation BeginTime="00:00:00"
Storyboard.TargetName="MyControl"
Storyboard.TargetProperty="ObjectWidth"
From="50" To="0"/>
The would also require you to add x:Name="MyControl" to your top-level UserControl. It's a little bit hacky, but it works to animate some of the underlying properties of elements that don't happen to be DependencyPropertys.
I would like to display an animation gif such as loading... in my XAML as my procedure is progressing. I found out that this cannot be easily done in WPF as I loaded my Gif and it just shows the first frame. What are the best ways to display an animation in WPF.
I had this issue, until I discovered that in WPF4, you can simulate your own keyframe image animations. First, split your animation into a series of images, title them something like "Image1.gif", "Image2,gif", and so on. Import those images into your solution resources. I'm assuming you put them in the default resource location for images.
You are going to use the Image control. Use the following XAML code. I've removed the non-essentials.
<Image Name="Image1">
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded"
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0:0:1" Storyboard.TargetProperty="Source" RepeatBehavior="Forever">
<DiscreteObjectKeyFrames KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image1.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:0.25">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image2.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image3.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:0.75">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image4.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:1">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image5.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Image.Triggers>
</Image>
You could embed a MediaElement
<MediaElement LoadedBehavior="Play" Source="path/to.file" />
or winforms PictureBox:
<wfi:WindowsFormsHost>
<winForms:PictureBox x:Name="pictureBoxLoading">
</winForms:PictureBox>
</wfi:WindowsFormsHost>
However, I'd recommend finding a way to do this in WPF. Have a look at StoryBoards and animations. Without knowing what you're trying to achieve or why you want to do this it's hard to advise further.
Simply Right Click on .gif file and change two properties:
Build Action : Embedded Resource
Copy To Output Directory : Copy if Newer
Then
<MediaElement x:Name="myGif" UnloadedBehavior="Manual" Source="giphy_s.gif" MediaEnded="MediaElement_MediaEnded"/>
and set Event For Continue Running
private void MediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
myGif.Position = new TimeSpan(0, 0, 1);
myGif.Play();
}