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();
}
Related
So this is probably a really simple answer. In my UWP app I've tried to start using the built-in Windows controls instead of my own buttons made from Borders around Textblocks. I'm doing this because it's simpler, but most importantly I need an easy to use toggle button.
I've learned about CommandBar and AppBarToggleButton and these seem to be exactly what I want. I'm able to set the background colour of the CommandBar just fine, but when toggled the AppBarToggleButton is always the user's accent colour. I need to be able to define it to match my app's branding (green). I have a feeling it requires me using some sort of theme as it's not in the xaml object's Brush properties menu, but I'm lost from then on out.
So this is my code, though it's very basic.
<CommandBar Background="{StaticResource MapButtonsBackgroundAcrylic}">
<AppBarToggleButton x:Name="tog_view_mode" Icon="View" Label="View Mode" Foreground="White"/>
<AppBarSeparator Foreground="White"/>
<AppBarToggleButton x:Name="tog_edit_mode" Icon="Edit" Label="Edit Mode" Foreground="White"/>
</CommandBar>
And this is what it gives me. My user accent colour is that blue. Also the change to black text isn't good.
As I'll have several toggles in my app, I'd like to either make a single style that I can assign them, or maybe change the accent colour that the app see's? I'm not sure what the correct procedure is here as I'm new to modifying built-in controls.
So I need a way for, when toggled,
The background to be green, say #FF008000
The foreground to be white.
Can anyone help me out?
You can override the style template for the AppBarToggleButton to achieve this.
To do this you need to right click on your AppBarToggleButton > Edit template > Edit a copy.
Then add the relevant code to the visual state. In your case the visual state is "Checked".
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckedHighlightBackground" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowCheckGlyph" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Your color here(green)"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="OverflowContentRoot" />
</Storyboard>
</VisualState>
Hope this helps.. please feel free to ask any questions that you might have..
You should override the AppBarToggleButtonBackground and other brushes in your App.xaml (if you want to apply to the whole app), in the Resources section of your page (if you want to apply to a specific page) or the same inside the actual toggle button (if you want to apply to a single button). The available resource keys are listed in the documentation.
I have a Grid which should be collapsed by default it is in A xaml file.
Another Button in Grid in another xaml file.When clcik button Grid should be enabled.
How to achieve this I have Tried this can you please help
<Grid Visibility={Binding Visibilityproperty}/>
<Button Content="A" Command={Binding VisibilityCommand"}/>
In button command i have written the logic to enable the visibilityproperty to visible
But grid is not at all visible if i do like this
Better solution in MVVM pattern is welcomed
<Button Content="Button!">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.Target="{x:Reference dataGrid}"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0"
Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
{x:Reference dataGrid} references a DataGrid with the name dataGrid, alternatively you could just use Storyboard.TargetName. You would normally use the Storyboard.Target property if you do binding or references to resources.
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.
Hi I got this Storyboard in WPF, that works great, but I need to load my user controls for Code Behind. (Some of them take some time to load, so I need to give the user info about the loading progress)
Anyway, this is my code right now.
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="businessCard"
Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:0.01">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
And I add them to my code with
<Grid Name="MyGrid">
<local:BusinessCard x:Name="businessCard"/>
<local:MailMessage x:Name="mailMessageCard"
DataContext="{Binding Path=SelectedItem, ElementName=foldersTreeView}" />
</Grid>
This Works, but as I mentioned I need to change it to run from Code Behind.
Was thinking about something like this, but I can't get the Binding to work.
var businessCard = new BusinessCard() {Name = "businessCard"};
MyGrid.Children.Add(businessCard);
Throws and Error
'businessCard' name cannot be found in the name scope of 'System.Windows.Controls.Grid'.
You can use the Storyboard.Target property instead of Storyboard.TargetName.
First remove the TargetName property of your XAML, and add a name to your animation, so you can reference it in code-behind:
<ObjectAnimationUsingKeyFrames x:Name="MyObjectAnimation" BeginTime="00:00:00"
Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:0.01">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
Then in your code-behind, after you create the object, update the animation:
var businessCard = new BusinessCard() {Name = "businessCard"};
MyGrid.Children.Add(businessCard);
MyObjectAnimation.SetValue(Storyboard.TargetProperty, businessCard)
Hope it helps!
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.