I'm making a windows store app and i'm trying to add a sound to the button for when you click it. I have my coding done, error free, but the sound does not play.
Any help is appreciated.
XAML
<Button x:Name="Explore" HorizontalAlignment="Left" Height="163" Margin="692,461,0,0" VerticalAlignment="Top" Width="546" BorderThickness="0" Click="Explore_Click"/>
<MediaElement x:Name="suprise" Source="Assets/suprise.mp3" AutoPlay="False" Visibility="Collapsed" HorizontalAlignment="Left" Height="147" Margin="108,285,0,0" VerticalAlignment="Top" Width="533" RenderTransformOrigin="0.5,0.5"/>
xaml.cs
private void Explore_Click(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(Explore));
suprise.Play();
}
The MediaElement needs to be in the visual tree to play and will stop when it is removed. Since Explore_Click navigates away before surprise has played, surprise isn't able to play its sound.
You have a few options:
Let surprise finish before calling Frame.Navigate. The app can handle surprise's MediaEnded event and navigate there.
Put surprise on the Explore page and play it when that page is reached
Use a global MediaElement in a page outside of the Frame containing the app's normal pages. This will let the MediaElement stay in the visual tree even as the app switches pages beneath it. This is generally needed if you want to play a consistent soundtrack during the app, but not so much for special effects. I discuss this method in more detail in my blog entry Frame of reference: keeping the music playing across pages
Related
My program should play a video when the user presses the 'Play' button. While it normally does this, the very first time they press the 'Play' button nothing will happen.
I have traced this bug back to the following code, which sets my MediaElement 'VideoPlayer':
public void playVideo_Tapped(object sender, TappedRoutedEventArgs e)
{
setUpVideo();
VideoPlayer.Play();
}
public async void setUpVideo()
{
if(vm == null) return;
StorageFile videoFile = vm.videoFile;
if (videoFile == null || !videoFile.ContentType.Equals("video/mp4")) return;
using (IRandomAccessStream fileStream = await videoFile.OpenAsync(FileAccessMode.Read))
{
VideoPlayer.SetSource(fileStream, videoFile.ContentType);
}
}
The culprit seems to be the 'SetSource()' method at the end. The only variable that changes from the first click of 'Play' to the next is the variable 'VideoPlayer.PlayToSource', which is changed from null to a real value.
(As a side note, the variable 'VideoPlayer.CurrentState' also changes from 'Closed' to 'Opening' but resets itself to 'Closed' before the second click. Only 'PlayToSource' changes the functionality.)
I figured that I could do a quick-fix by doing this in my first method:
setUpVideo();
setUpVideo();
VideoPlayer.Play();
Not great code but it ought to set things straight, right? Nope! This causes a NullReferenceException. On the second call to 'setUpVideo()' I find that 'PlayToSource' still has a value and 'VideoPlayer.CurrentState' is still set to 'Opening'... which somehow triggers the NullReferenceException.
I'm expecting the solution to be one of the following things:
1.) Set 'VideoPlayer.PlayToSource' on the first click before calling 'SetSource'.
2.) In the quick-fix, set 'VideoPlayer.CurrentState' back to 'Closed' in between calls.
3.) Some other thing that mimics what the first click is doing.
Of course, both of my ideas involve changing a read-only variable. Which is where I'm getting stuck. I'll include the .xaml code for good measure, but I'm confident that it's the method 'SetSource' that's the root of my troubles:
<Grid x:Name="VideoViewerParentGrid" Background="DarkGreen" Height="{Binding VideoViewerParentGridHeight }" Width="{Binding VideoViewerParentGridWidth}">
<MediaElement x:Name="VideoPlayer" HorizontalAlignment="Center" VerticalAlignment="Bottom" Stretch="Uniform"
Visibility="{Binding VideoVisibility, Converter={StaticResource visibilityConverter}}"/>
<Button Style="{StaticResource BackButtonStyle}" Tapped="VideoViewerClose_Tapped" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Button Name="Play_Button" Content="Play Video" FontSize="26" Tapped="playVideo_Tapped"
VerticalAlignment="Top" HorizontalAlignment="Left" Height="60" Width="180" Margin="0,80,0,0"/>
</Grid>
---- UPDATE ----
Some more poking has revealed that on the first click 'VideoPlayer.CurrentState' never reaches the 'Playing' state, instead going from 'Opening' right back to 'Closed'. It does not do this on any subsequent clicks for as long as the program is running. Still investigating the cause of this.
You are missing the "await" keyword. Do this:-
await setUpVideo();
Short version, this issue is fixed by changing this:
using (IRandomAccessStream fileStream = await videoFile.OpenAsync(FileAccessMode.Read))
{
VideoPlayer.SetSource(fileStream, videoFile.ContentType);
}
...to be this:
IRandomAccessStream fileStream = await videoFile.OpenAsync(FileAccessMode.Read);
VideoPlayer.SetSource(fileStream, videoFile.ContentType);
Longer version, my code was failing because of the error "mf_media_engine_err_src_not_supported hresult - 0xc00d36c4", which was closing my MediaElement instead of playing it. This was happening because when I left the 'using' block of code the 'IRandomAccessStream' would close in the middle of my reading of the file. I'm not 100% clear why it gets through the whole thing after the first run of the code, but at least it now works reliably.
I've also got to give credit where credit is due, and I found this answer here: Windows 8 app - MediaElement not playing ".wmv" files
I'm trying to bind some (HD) photos to a LongListSelector as you can see here:
<phone:LongListSelector
Name="Photos"
LayoutMode="Grid"
ItemsSource="{Binding Items}"
GridCellSize="225, 225"
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Grid>
<Image Name="Photo"
Source="{Binding Source}"
</Grid>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
foreach (string item in resultList)
{
u = new Uri(item, UriKind.RelativeOrAbsolute);
this.Items.Add(new DataItemViewModel() { Source = u});
}
});
but everytime I go back to the main page and click to start this all over again (with new/different photos) the ApplicationPeakMemoryUsage just keeps increasing until the app terminates itself...
I'm sorry if it's a basic question but I'm a newbie in C#.
Any hints?
(Maybe a way to dispose the LongListSelector or the whole page when the user hits the back button)
Thank You.
Last time I had this problem I used the IDipose pattern. The problem I had was when using third party dll's, the CLR was not cleaning the objects from the dll.
After I implemented the IDispose pattern and whenever I used that specific object, I put it within the 'using' statement which ensured that it was disposed of at the end of the 'using' statement's scope. More information on the using statement: http://www.dotnetperls.com/using
To make me realise this in the first place I debugged my code and watched Task Manager. Make a breakpoint at the start of the code, and open up task manager and click on the Processes tab.
After certain points where you think the problem may lie, watch where the memory usage increases a lot.
Get back to me when you have done this.
Hope it helps, get back to me if nothing works :)
I have some page with TextBox or PhoneTextBox (from toolkit): Part of xaml code.
I animate scrollviewer (opacity and XProperty), befor I set datacotext for textbox.
<ScrollViewer x:Name="ContentScroller"
Visibility="Collapsed"
Margin="35,0,35,0">
<ScrollViewer.RenderTransform>
<TranslateTransform />
</ScrollViewer.RenderTransform>
<Grid x:Name="ContentGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock x:Name="CreationgDate"
Text="{Binding CreationDate, StringFormat='Created: {0:dd.MM.yyyy HH:mm}'}"
Style="{StaticResource CreationDateTextStyle}"
Grid.Row="0"/>
<toolkit:PhoneTextBox x:Name="BodyData"
InputScope="Chat"
Text="{Binding Body, UpdateSourceTrigger=Explicit}"
LostFocus="BodyData_LostFocus"
TextWrapping="Wrap"
AcceptsReturn="True"
Grid.Row="1">
</toolkit:PhoneTextBox>
</Grid>
</ScrollViewer>
I update DataSource in event LostFocus:
// this I set datacontex
private async void Item_Click(object sender, RoutedEventArgs e)
{
PageHeader.DataContext = CreationgDate.DataContext = BodyData.DataContext = activeItem;
await AnimateChangePage();
}
private void BodyData_LostFocus(object sender, RoutedEventArgs e)
{
BindingExpression be = NoteBodyData.GetBindingExpression(PhoneTextBox.TextProperty);
be.UpdateSource();
}
TROUBLE: When text in textbox has 400-500 chars and more, then text input in textbox very slow, and keyboard have a lag response.
I test app in real device (not emulator), other app with same functionality (from app store) work fine without lag and slow input.
Help me with this thing please.
And sorry for my lang (not english) :) .
Following our comment discussion, this is the best answer I can give:
Run the app on your phone in debug mode.
Either straight away, or when the issue occurs, set a breakpoint in the set statement on the body property(above if property=value). When the breakpoint is hit, use the call stack to work out what is causing the update and the watch window to see the current value. You may find something is trying to update it repeatedly.
If there is anything else updating the body, there are subscribed events, or viewmodel events being fired that relate to the body, stick breakpoints on them and see if they are firing excessively.
Failing that, Stick breakpoints everywhere. For example, it may be losing focus for some reason, and triggering that event more than it should be. It could also be something else rending in the background.
All that fails, try not binding the textbox and going WinForms style of set the value and then get it back later. Remove all unnecessary events. You can then build it back up and identify the cause. If it is slow without a binding and attached events, then I really would be out of ideas.
Generally, i have found this sort of thing relates to events firing that I didn't expect. I see you are checking the incoming value is different, which will stop the dreaded MVVM property loop, but without seeing the rest of the application, its hard to narrow the issue down further.
I have WP7 application with several pages. When a user navigates through them it takes some time to load information. So before showing him/her the page I'd like to show “Loading…” message.
I created progress bar and placed it on the page:
<StackPanel x:Name="progressBarMain" Grid.Row="1" Grid.ColumnSpan="2" Visibility="Collapsed">
<TextBlock Text="Loading..." HorizontalAlignment="Center" VerticalAlignment="Center" />
<ProgressBar Margin="10" Height="30" IsIndeterminate="True"/>
</StackPanel>
And I'm trying to show it (and hide everything else) in the page's constructor, and hide it (and show everything else) in Page.Loaded handler.
public SomePage()
{
InitializeComponent();
Loaded +=OnSomePageLoaded;
progressBarMain.Visibility = Visibility.Visible;
ContentPanel.Visibility = Visibility.Collapsed;
}
private void OnSomePageLoaded(object sender, RoutedEventArgs e)
{
progressBarMain.Visibility = Visibility.Collapsed;
ContentPanel.Visibility = Visibility.Visible;
}
But it doesn’t' work.
Any ideas? Thank you!
Alex demonstrates showing a progress bar while the app is starting up here.
Creating a Splash Screen with a progress bar for WP7 applications. - Alex Yakhnin's Blog
Although you cannot directly manipulate the splash screen (which is static), you can display a popup (by the way, that is exactly what is done in Alex's solution) and wait for a background (read: loading) operation to complete.
Yes, you'll need to create a separate XAML Pop-up page that is loaded when the app boots up. For more details on Splash Screens, there is a code sample from MSDN:
"Code Sample for Splash Screen"
I have an image control that I want it to load the image asynchronously over the network. I see some sample code in the network saying something like:
<Image HorizontalAlignment="Left" Height="118" Margin="2,8,0,0" VerticalAlignment="Top" Width="167" x:Name="ImageThumbnail" Source="{Binding SummaryImageLink, IsAsync=True}" />
However, in Windows Phone 7, I cannot find anything like that. Does anybody know a way to do that without I have to code a lot myself
Unfortunately you are going to have to write, or include, more code yourself to do this properly. I have a similar solution with the goal to cache images after the first download. The image cache class is accessed via a IValueConverter, so once you have included the appropriate code, you only have to add a decorator on the Image object:
<Image Source="{Binding ElementName=ImageSource, Path=Text, Converter={StaticResource imageCacheConverter}}" Width="200" />
Full details here and source code here: http://www.ben.geek.nz/2010/07/one-time-cached-images-in-windows-phone-7/
David Anson's work with LowProfileImageLoader may be of interest to you.
Keep a low profile [LowProfileImageLoader helps the Windows Phone 7 UI thread stay responsive by loading images in the background] - Delay's Blog
Alternatively you can asynchronously download the picture (for ex. with a BackgroundWorker) and assign it as source for your image control only when the download has completed.