I am trying to play some background music in a WPF application but the music does not play when I am using a relative path.
This does not work:
<Storyboard x:Key="PlaySoundStoryboard">
<MediaTimeline Storyboard.TargetName="myMediaElement" Source="pack://application:,,,/Music/music.mp3" />
</Storyboard>
However when I pick the full path as source it does work:
(The music also plays when I do not run the application, but just have the code open in Visual Studio, so if anybody has a fix for that please let me know)
<Storyboard x:Key="PlaySoundStoryboard">
<MediaTimeline Storyboard.TargetName="myMediaElement" Source="D:\Documenten\Application\View\Music\music.mp3" />
</Storyboard>
I also tried just specifying the folder as suggested here: Set Mediaelement Source to Relative URI in WPF Code
<Storyboard x:Key="PlaySoundStoryboard">
<MediaTimeline Storyboard.TargetName="myMediaElement" Source="Music/music.mp3" />
The relative path does work when I use it for images so I am a little bit confused,
this works:
<Button.Content>
<Image Source="pack://application:,,,/Img/music-and-multimedia.png"/>
</Button.Content>
Edit: Here is my media element
<MediaElement x:Name="myMediaElement" />
<Button Name="playbutton" Grid.Column="0" Width="40" Height="40" Background="Transparent" BorderThickness="0" HorizontalAlignment="Left">
<Button.Content>
<Image Source="pack://application:,,,/Img/music-and-multimedia.png"/>
</Button.Content>
</Button>
<Button Name="stopbutton" Grid.Column="1" Width="40" Height="40" Background="Transparent" BorderThickness="0" HorizontalAlignment="Left">
<Button.Content>
<Image Source="pack://application:,,,/Img/mute.png"/>
</Button.Content>
</Button>
And here are my Grid.Triggers:
<Grid.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource PlaySoundStoryboard}" Name="theStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="playbutton">
<ResumeStoryboard BeginStoryboardName="theStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="stopbutton">
<PauseStoryboard BeginStoryboardName="theStoryboard" />
</EventTrigger>
</Grid.Triggers>
It is possible to resolve this problem by extracting audio/media content from a resources and write it to the temporary file. Then set URI for the MediaTimeline source to make reference to the temporary file.
var resourceName = "YourAssemblyName.Music.music.mp3"; // Embedded resource
using (var fstream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
var ext = resourceName.Substring(resourceName.LastIndexOf("."));
var pathfile = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ext;
using (FileStream outputFileStream = new FileStream(pathfile, FileMode.Create))
{
fstream.CopyTo(outputFileStream);
}
// "mt" is name of the MediaTimeline element
mt.Source = new Uri(pathfile, UriKind.RelativeOrAbsolute);
}
Remove the temporary created file pathfile when it no longer needed.
Related
I'm working with new MS technology UWP. I have 2 images in DataTemplate, CopyImage and MainImage. It's because of image flickering, when source is changed. So I would like to ask, how can I set the source of CopyImage, when event Loaded of MainImage is fired? In WPF I can use DataTriggers, but they are not in UWP. I want to do that in XAML, no in code-behind.
Many thanks guys
EDIT
<Image Grid.Column="0" x:Name="MainImage" Source="{x:Bind ImageStatusUri, Mode=OneWay}" Margin="0,8,12,8">
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded">
</EventTrigger>
</Image.Triggers>
I hope you are using Template10
<Page xmlns:interact="using:Microsoft.Xaml.Interactivity"
xmlns:interactcore="using:Microsoft.Xaml.Interactions.Core">
...
<Image Grid.Column="0" x:Name="MainImage" Source="{x:Bind ImageStatusUri, Mode=OneWay}" Margin="0,8,12,8" >
<interact:Interaction.Behaviors>
<interactcore:EventTriggerBehavior EventName="Loaded">
<interactcore:ChangePropertyAction PropertyName="Source" Value="" TargetObject="{Binding ElementName=CopyImage}"/>
</interactcore:EventTriggerBehavior>
</interact:Interaction.Behaviors>
</Image>
</Page>
I have a Gridwhich I'm able to animate the following way:
When I click on the image, I can animate the template of my button with a Storyboard to grow as much as I want as a result like this:
That would be the result more or less. The animation looks like this:
<Storyboard x:Key="ExpandPanelRight">
<DoubleAnimation
Storyboard.TargetName="ExpandablePanel"
Storyboard.TargetProperty="Width"
BeginTime="0:0:0"
From="0" To="450" Duration="0:0:0.5"></DoubleAnimation>
</Storyboard>
As you can see, no problem while growing the grid from left to right, but what I really want is the opposite: expand the Grid from right to left:
How will it be?? I can't find the answer.
All you need to do is to align your bin Image to the right edge of your ExpandablePanel. Once you have done that then the Image will stick to the right hand side as the Width of the Panel increases. your Storyboard and DoubleAnimation code can remain the same. Your code should look something like this:
<Border CornerRadius="10" Background="Blue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="Expanding...." VerticalAlignment="Center" />
<Image Source="Images/Bin.png" VerticalAlignment="Center" HorizontalAlignment="Right" />
</Grid>
</Border>
I'm attempting to flip a button on a form using a storyboard. What I currently have is a storyboard that uses a custom grid animation to make certain grid rows grow (found here). The button that I have that initiates this storyboard has an image of arrows overlayed on it and it needs to be flipped to correct the direction of the control for the user to understand. The storyboard that I have works (as in it doesn't produce any errors) but it only makes the gridrow height property grow; the button image is not flipped vertically.
<!-- "Open the description box" Storyboard-->
<Storyboard x:Key="openDescription">
<local:GridLengthAnimation
Storyboard.TargetName="Row4"
Storyboard.TargetProperty="Height"
From="0*" To=".5*" Duration="0:0:1"
AccelerationRatio=".5"
DecelerationRatio=".5"/>
<!-- This is the section that needs to be tweaked -->
<DoubleAnimation
Storyboard.TargetName="btnDetailsZoom"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
From="0"
To="-1"
Duration="00:00:01"/>
</Storyboard>
<!-- Code for the button -->
<s:SurfaceButton Grid.Row="4" Grid.Column="4" VerticalAlignment="Top" Margin="25,-50,25,-50" Name="btnDetailsZoom" PreviewTouchDown="onDetailsZoom">
<s:SurfaceButton.Background>
<ImageBrush ImageSource="/uiTest2;component/Resources/doubleArrowUp.png" />
</s:SurfaceButton.Background>
</s:SurfaceButton>
If anyone knows about how to correctly use the scaletransform property within a storyboard (since I'm fairly sure that's partially correct), I would greatly appreciate some guidance.
Thanks!
It looks like you forgot to define the Transform Property on the Button, like this:
<!-- Code for the button -->
<s:SurfaceButton Grid.Row="4" Grid.Column="4" VerticalAlignment="Top" Margin="25,-50,25,-50" Name="btnDetailsZoom" PreviewTouchDown="onDetailsZoom">
<s:SurfaceButton.RenderTransform>
<ScaleTransform />
</s:SurfaceButton.RenderTransform>
<s:SurfaceButton.Background>
<ImageBrush ImageSource="/uiTest2;component/Resources/doubleArrowUp.png" />
</s:SurfaceButton.Background>
</s:SurfaceButton>
I am trying to rotate an image and want to use a storyboard as in the next phases i need to add multiple animations running to time.
my code is inside a click event of a button as follows:
//start the animation
DoubleAnimation animationRotation = new DoubleAnimation();
animationRotation.From = -17;
animationRotation.To = 17;
animationRotation.Duration = new Duration(TimeSpan.FromMilliseconds(NumericDisplay.Milliseconds));
animationRotation.RepeatBehavior = RepeatBehavior.Forever;
animationRotation.AccelerationRatio = 0.3;
animationRotation.DecelerationRatio = 0.3;
animationRotation.AutoReverse = true;
Storyboard storyboard = new Storyboard();
Storyboard.SetTarget(animationRotation, Arm);
Storyboard.SetTargetProperty(animationRotation,
new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"));
storyboard.Children.Add(animationRotation);
// Add the storyboard to the tracking collection.
//this.Stostoryboards.Add(bomb, storyboard);
// Configure and start the storyboard.
this.BeginStoryboard(storyboard);
the code compiles without warning yet the click event does not start the animation,
EDIT
One of the proposed answers asked me to check the XAML included a definition for rotatetransform ... the XAML below is what I am using
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
<ImageBrush x:Key="ImageBrush_Decrement" ImageSource="Images/pad-metronome-decrement-button.png" Stretch="Fill"/>
<ImageBrush x:Key="ImageBrush_Increment" ImageSource="Images/pad-metronome-increment-button.png" Stretch="Fill"/>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
</EventTrigger>
</UserControl.Triggers>
<Grid x:Name="LayoutRoot" Height="412">
<Image x:Name="MetronomeWindowBackground" Height="140" Margin="237,1.5,231,0" Source="Images\pad-metronome-top-under-bg.png" Stretch="Fill" VerticalAlignment="Top"/>
<Image x:Name="Arm" Margin="506,17,493,0" Source="Images\pad-metronome-arm.png" Stretch="Fill" Height="326" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<RotateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
<Image x:Name="MetronomeFlash" Height="209" Margin="104,0,96,0" Source="Images\pad-metronome-flash-top-landscape.png" Stretch="Fill" VerticalAlignment="Top" d:IsHidden="True" />
<Image x:Name="MetronomeBackground" Height="209" Source="Images\pad-metronome-top-bg-landscape.png" Stretch="Fill" VerticalAlignment="Top" Margin="3,0,-3,0"/>
<Image x:Name="MetronomeStartButton" Margin="379.5,100.5,373.5,0" Source="Images\pad-metronome-start-button-base.png" Stretch="Fill" Height="110" VerticalAlignment="Top"/>
<Image x:Name="MetronomeTapPadLeft" HorizontalAlignment="Left" Height="209" Margin="5,1.5,0,0" Source="Images\pad-metronome-tap-pad-left.png" Stretch="Fill" VerticalAlignment="Top" Width="136"/>
<Image x:Name="MetronomeTapPadRight" HorizontalAlignment="Right" Source="Images\pad-metronome-tap-pad-right.png" Stretch="Fill" Width="136" Height="209" VerticalAlignment="Top"/>
<Image x:Name="MetronomeWindowHighlight" Height="105" Margin="238.5,18,231.5,0" Source="Images\pad-metronome-window-overlay.png" Stretch="Fill" VerticalAlignment="Top"/>
<Image x:Name="MetronomeBottomBackground" Margin="3,208,-3,362" Source="Images\pad-metronome-section-bottom-bg.png" Stretch="Fill"/>
<my:MetronomeLargeNumericDisplay HorizontalAlignment="Left" Margin="459,120,0,0" x:Name="NumericDisplay" VerticalAlignment="Top" Value="999" Width="122.25" />
<Image Height="78" Margin="448,110.5,436,0" Source="Images\pad-metronome-start-button-overlay.png" Stretch="Fill" VerticalAlignment="Top"
x:Name="DisplayOverlay" MouseDown="DisplayOverlay_MouseDown" />
<RepeatButton x:Name="ButtonDecrement" Content="" BorderThickness="7" HorizontalAlignment="Left" Margin="252,110.5,0,0" VerticalAlignment="Top" Width="149" Height="100" Background="{DynamicResource ImageBrush_Decrement}" Style="{DynamicResource RepeatButtonStyle_noflash}" BorderBrush="{DynamicResource ImageBrush_Decrement}" d:LayoutOverrides="HorizontalAlignment" Click="ButtonDecrement_Click"></RepeatButton>
<RepeatButton Content="" BorderThickness="7" HorizontalAlignment="Left" Margin="631,110.5,0,0" VerticalAlignment="Top" Width="149" Height="100" Background="{DynamicResource ImageBrush_Increment}" Style="{DynamicResource RepeatButtonStyle_noflash}" BorderBrush="{DynamicResource ImageBrush_Decrement}" Name="ButtonIncrement" Click="ButtonIncrement_Click" />
</Grid>
what am I doing wrong?
The code you've posted seems to be ok, however, the path refers to an existing element, so make sure you've included appropriate nodes in xaml, where Arm control is defined.
Let's say Arm is a Rectangle control. Your xaml should then look more or less like this:
...
<Rectangle x:Name="Arm" Fill="Aqua" Width="100" Height="100" Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<TransformGroup>
<RotateTransform />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
...
Arm can be another type of control, but the important thing is that RenderTransform, TransformGroup and RotateTransform nodes are defined, so animation has some existing elements to change as specified in the PropertyPath in your code.
after much messing around with new projects and much simplified code I asked the question slightly differently in another thread and someone posted working code.
on investigation that reason my animation was not working was that I had provided a duration to the animation but not the storyboard itself !! doh.
full answer here (which is one of the fullest answers I have received on this topic)
How do I create a rotate animation on an image object using c# code only (inside a WPF window)
Lucas, thanks to you for your patience and assistance on this question.
Dan
I am making silverlight program where user can add worms to ground. Worms has to modifable. They can have three or more controlpoints where from user can move and edit worm. Worm has to have maximum and minimum length. Also it has to somekind outfit that it looks like worm. I have made pretty good worm with canonical spline but problem is max and minimum lengths and outfit. i am not waiting any ready codes for this but some new ideas how it can be done.
Example made by MSPaint :) http://tinypic.com/r/bgxp3m/7
You can use the Pen tool in Expression Blend to create an open path with bezier curves. Then the Direct Selection tool can modify the points to give you the desired shape. If you do this in a Storyboard, Expression Blend will expand the Path data into uncompressed format, which can be animated, named, and referenced from code behind. Here is a sample worm:
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<Storyboard x:Name="wriggle">
<PointAnimation Duration="0:0:0.7" To="59.4217224121094,11.1413049697876" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point1)" Storyboard.TargetName="wormBody" d:IsOptimized="True"/>
<PointAnimation Duration="0:0:0.7" To="21.5,45.9078826904297" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point2)" Storyboard.TargetName="wormBody" d:IsOptimized="True"/>
<PointAnimation Duration="0:0:0.7" To="9.25,28.6580047607422" Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point1)" Storyboard.TargetName="wormBody" d:IsOptimized="True"/>
</Storyboard>
</Grid.Resources>
<Path x:Name="wormBody" HorizontalAlignment="Left" Height="67.316" Margin="167,150.092,0,0" Stroke="Black" StrokeThickness="10" UseLayoutRounding="False" VerticalAlignment="Top" Width="91">
<Path.Data>
<PathGeometry FillRule="EvenOdd">
<PathFigure IsFilled="True" IsClosed="False" StartPoint="5,62.3157653808594">
<BezierSegment Point3="42.2093734741211,24.9581699371338" Point2="4.49375009536743,30.3548755645752" Point1="35.375,53.3601760864258"/>
<BezierSegment Point3="86,5" Point2="73.8499984741211,24.9581699371338" Point1="54.1062507629395,22.6553039550781"/>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
<Ellipse HorizontalAlignment="Left" Height="15" Margin="246,146,0,0" Stroke="Black" StrokeThickness="10" VerticalAlignment="Top" Width="15"/>
</Grid>