Play audio file in the background in Windows8 app? - windows-8

I am developing an app that displays information while at the same time plays audio file in the background. This is a Windows 8 tablet app. Any help or suggestion is helpful.
Thanks

In the XAML, you will have a MediaElement with the following attributes
<ContentControl x:Name="Host">
<MediaElement Source="Assets/myMusic.mp3" IsLooping="True" AutoPlay="True" AudioCategory="BackgroundCapableMedia" PosterSource="/Images/placeholder-sdk.png" VerticalAlignment="Center" HorizontalAlignment="Center" Name="myMediaElement" Height="350" Width="640" />
</ContentControl>
In the App bar, you can have some buttons for media control like
<Page.BottomAppBar>
<AppBar Opened="BottomAppBar_Opened" Background="#FF3C3838" x:Name="BottomAppBarColors" Padding="10,0,10,0" AutomationProperties.Name="Bottom App Bar Colors">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"/>
<ColumnDefinition Width="50*"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="LFullScreenLandscapeViewGrid" Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left">
<Button x:Name="Play" Click="PlayButton_Click" Style="{StaticResource PlayAppBarButtonStyle}" Tag="Play"/>
<Button x:Name="Stop" Click="StopButton_Click" Style="{StaticResource StopAppBarButtonStyle}" Tag="Stop"/>
</StackPanel>
<StackPanel Visibility="Collapsed" x:Name="PortraitViewGrid" Orientation="Horizontal" Grid.ColumnSpan="2" HorizontalAlignment="Right">
<Button x:Name="PauseCollapsed" Click="PauseButton_Click" Style="{StaticResource PauseAppBarButtonStyle}" Tag="Pause"/>
<Button x:Name="PlayCollapsed" Click="PlayButton_Click" Style="{StaticResource PlayAppBarButtonStyle}" Tag="Play"/>
<Button x:Name="StopCollapsed" Click="StopButton_Click" Style="{StaticResource StopAppBarButtonStyle}" Tag="Stop"/>
</StackPanel>
</Grid>
</AppBar>
</Page.BottomAppBar>
In the .CS code file, you can control the mediaelement object.
private void PauseButton_Click(object sender, RoutedEventArgs e)
{
myMediaElement.Pause();
}
private void StopButton_Click(object sender, RoutedEventArgs e)
{
myMediaElement.Stop();
}
private void ForwardButton_Click(object sender, RoutedEventArgs e)
{
myMediaElement.DefaultPlaybackRate = 0.0;
myMediaElement.PlaybackRate = 2.0;
}
private void RewindButton_Click(object sender, RoutedEventArgs e)
{
myMediaElement.DefaultPlaybackRate = 0.0;
myMediaElement.PlaybackRate = -1.0;
}

If you have multiple screens that use the media and controls to play, pause and stop the media file, then it's better to write code for these events once and then use it from different screens. I have seen people writing the following code in every screen they use the media.
private void PauseButton_Click(object sender, RoutedEventArgs e)
{
myMediaElement.Pause();
}
private void StopButton_Click(object sender, RoutedEventArgs e)
{
myMediaElement.Stop();
}
private void ForwardButton_Click(object sender, RoutedEventArgs e)
{
myMediaElement.DefaultPlaybackRate = 0.0;
myMediaElement.PlaybackRate = 2.0;
}
private void RewindButton_Click(object sender, RoutedEventArgs e)
{
myMediaElement.DefaultPlaybackRate = 0.0;
myMediaElement.PlaybackRate = -1.0;
}
So instead of repeating the code in every screen, follow a good event pattern to reduce duplicate code
The best thing is to use MVVM pattern and you can find a sample at http://code.msdn.microsoft.com/windowsapps/Background-Audio-c-Metro-d2fc7719/view/SourceCode
So the design is to write up the code in one common place and fire them from the front end UI.

You need to use a MediaElement.

Related

How to create an identical button to the one in 'Settings' page?

I want to create buttons on my UWP/XAML app similar to the buttons on the Windows 'Settings' page using the WinUI 3 library. The gallery didn't show this kind of button with an icon and a title/description. I'm wondering how it can be accomplished since I am developing an app that mostly serves as a portal to go to websites and navigate easily through web/PC apps. Any help would be appreciated.
I want the buttons to simply redirect the user to a NavigationView page (Page5.xaml)
I have a NavigationView on MainPage.xaml and these buttons are going on Page4, so I'm not sure how I can program the buttons to go to Page5.xaml
https://i.stack.imgur.com/7Uff8.png
You can create a usercontrol and use some of my code:
MyUserControl.xaml:
<Grid x:Name="MainGrid" PointerEntered="Grid_PointerEntered" PointerExited="Grid_PointerExited" PointerPressed="FontIcon_PointerPressed" Margin="20,5,20,5" Height="70" CornerRadius="5" Padding="{StaticResource ExpanderHeaderPadding}" HorizontalAlignment="Stretch" Background="{ThemeResource ExpanderHeaderBackground}" BorderThickness="{ThemeResource ExpanderHeaderBorderThickness}" BorderBrush="{ThemeResource ExpanderHeaderBorderBrush}">
<StackPanel Orientation="Horizontal" Margin="0,20,0,20">
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" Margin="0,0,20,0"/>
<TextBlock FontSize="24" VerticalAlignment="Center" HorizontalAlignment="Left" Text="Font"/>
</StackPanel>
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" HorizontalAlignment="Right" Margin="0,0,20,0"/>
</Grid>
MyUserControl1.xaml.cs:
public MyUserControl1()
{
this.InitializeComponent();
var color = (MainGrid.Background as SolidColorBrush).Color;
color.A = 20;
MainGrid.Background = new SolidColorBrush(color);
}
private void FontIcon_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (e.GetCurrentPoint(sender as UIElement).Properties.IsLeftButtonPressed)
{
//Do whatever you want
Debug.WriteLine("Pressed");
}
}
//Change the color on hover:
private void Grid_PointerEntered(object sender, PointerRoutedEventArgs e)
{
var color = (MainGrid.Background as SolidColorBrush).Color;
color.A = 50;
MainGrid.Background = new SolidColorBrush(color);
}
private void Grid_PointerExited(object sender, PointerRoutedEventArgs e)
{
var color = (MainGrid.Background as SolidColorBrush).Color;
color.A = 20;
MainGrid.Background = new SolidColorBrush(color);
}

How to set the visiblility of a grid when the grid is inside a DataTemplate?

In our UWP app the DataTemplate for MyListView is set in the code behind to either DataTemplateA or DataTemplateB in Page.Resources. Each data template contains a grid (TopGrid) which contains a DisplayGridButton and another grid (DisplayGrid).
DisplayGrid contains SecondListView and a HideGridButton
DisplayGridButton should show DisplayGrid. HideGridButton should collapse DisplayGrid.
The XAML is
<Page.Resources>
<DataTemplate x:Key="DataTemplateA">
<Grid Name="TopGrid">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBox/>
<Button Name="DisplayGridButton" Content="Show" Margin="10,0" Click="DisplayGridButton_Click"/>
</StackPanel>
<Grid Name="DisplayGrid" Grid.Row="1" Visibility="Collapsed">
<StackPanel>
<Button Name="HideGridButton" Content="Hide" Click="HideGridButton_Click"/>
<ListView Name="SecondListView">
<ListView.ItemTemplate>
<DataTemplate >
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
</Grid>
</DataTemplate>
<DataTemplate x:Key="DataTemplateB">
<Grid Name="TopGrid">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBox/>
<Button Name="DisplayGridButton" Content="Show" Margin="10,0" Click="DisplayGridButton_Click"/>
</StackPanel>
<Grid Name="DisplayGrid" Grid.Row="1" Visibility="Collapsed">
<StackPanel>
<Button Name="HideGridButton" Content="Hide" Click="HideGridButton_Click"/>
<ListView Name="SecondListView">
<ListView.ItemTemplate>
<DataTemplate >
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView Name="MyListView">
</ListView>
</Grid>
DataTemplateA or DataTemplateB is set in the code behind.
if (condition)
{
MyListView.ItemTemplate = (DataTemplate)Resources["DataTemplateA"];
}
else
{
MyListView.ItemTemplate = (DataTemplate)Resources["DataTemplateB"];
}
In the Code behind I can create the event handler but I cannot access the DisplayGrid to make it visible or to collapse it.
I would normally set visibility like this.
private void DisplayGridButton_Click(object sender, RoutedEventArgs e)
{
DisplayGrid.Visibility = Visibility.Visible;
}
private void HideGridButton_Click(object sender, RoutedEventArgs e)
{
DisplayGrid.Visibility = Visibility.Collapsed;
}
How do I access the DisplayGrid in the DataTemplate from the button click events?
Since the grid is defined in a template, you'll have to dig it out at runtime. (If you could reference it as "DisplayGrid" from code-behind, you wouldn't know which listview item it belonged to anyway.)
Implement click handlers something like this:
private void DisplayGridButton_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
StackPanel stackPanel = button?.Parent as StackPanel;
Grid grid = stackPanel?.Parent as Grid;
if (grid != null)
{
Grid displayGrid = FindVisualChild<Grid>(grid, "DisplayGrid");
if (displayGrid != null)
{
displayGrid.Visibility = Visibility.Visible;
}
}
}
private void HideGridButton_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
StackPanel stackPanel = button?.Parent as StackPanel;
Grid grid = stackPanel?.Parent as Grid;
if (grid != null)
{
grid.Visibility = Visibility.Collapsed;
}
}
(Fair warning: The way this code finds the appropriate parent to start from is a bit brittle; it might break if the template changes. Searching by name would be better, but I don't have anything handy right now.)
Here is the helper method that finds a named child in the visual tree:
public static T FindVisualChild<T>(
DependencyObject parent,
string name = null)
where T : DependencyObject
{
if (parent != null)
{
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
T candidate = child as T;
if (candidate != null)
{
if (name == null)
{
return candidate;
}
FrameworkElement element = candidate as FrameworkElement;
if (name == element?.Name)
{
return candidate;
}
}
T childOfChild = FindVisualChild<T>(child, name);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return default(T);
}
(This method can also search by type only; just pass null as the name.)

Flyout won't change to dark theme?

The flyout doesn't change its theme from light to dark. I don't know why.
See my Example Code below. You can change the theme here and then the flyout remains in light theme.
MainPage.xaml
<Page>
<Page.BottomAppBar>
<CommandBar>
<AppBarButton Icon="Emoji">
<AppBarButton.Flyout>
<Flyout/>
</AppBarButton.Flyout>
</AppBarButton>
<AppBarToggleButton Checked="Checked" Unchecked="Unchecked">
<AppBarToggleButton.Icon>
<FontIcon Glyph="" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
</CommandBar>
</Page.BottomAppBar>
</Page>
MainPage.cs
public sealed partial class MainPage : Page
{
private void Checked(object sender, RoutedEventArgs e)
{
this.RequestedTheme = ElementTheme.Dark;
}
private void Unchecked(object sender, RoutedEventArgs e)
{
this.RequestedTheme = ElementTheme.Light;
}
}
If you placed content inside the flyout, you will find that they adapt to the new ElementTheme, however the flyout presenter itself won't change it's background.
The flyout presenter follows the ApplicationTheme which you can't change in code behind while the app is running, but I have two workarounds for this issue:
Specific Flyout approach, define
Define <SolidColorBrush x:Key="FlyoutBackBrush" Color="#FF2B2B2B"/> in App.Xaml resources
Define FlyoutPresenterStyle and make background uses the brush we just defined in App.Xaml
<Flyout x:Name="MyFlyout">
<Flyout.FlyoutPresenterStyle>
<Style TargetType="FlyoutPresenter">
<Setter Property="Background" Value="{StaticResource FlyoutBackBrush}"/>
</Style>
</Flyout.FlyoutPresenterStyle>
<StackPanel>
<Button Content="Button"/>
<TextBlock Text="Test"/>
</StackPanel>
</Flyout>
Change color property of the the resource FlyoutBackBrush and it will reflect in Flyout's background.
private readonly Color _darkColor = Color.FromArgb(255, 43, 43, 43);//themeresources.xaml - Default
private readonly Color _lightColor = Color.FromArgb(255, 242, 242, 242);//themeresources.xaml - Light
private void SetFlyoutBackBrush(Color color)
{
var brushKey = "FlyoutBackBrush";
if (Resources.ContainsKey(brushKey))
{
var flyoutbackBrush = Resources[brushKey] as SolidColorBrush;
if (flyoutbackBrush != null) flyoutbackBrush.Color = color;
}
}
private void Checked(object sender, RoutedEventArgs e)
{
this.RequestedTheme = ElementTheme.Dark;
SetFlyoutBackBrush(_darkColor);
}
private void Unchecked(object sender, RoutedEventArgs e)
{
this.RequestedTheme = ElementTheme.Light;
SetFlyoutBackBrush(_lightColor);
}
[Not recommended] Wide effect approach, by retrievingSystemControlBackgroundChromeMediumLowBrush's from application resources and changing it's color value [Works but read Note]
private readonly Color _darkColor = Color.FromArgb(255, 43, 43, 43);//themeresources.xaml - Default
private readonly Color _lightColor = Color.FromArgb(255, 242, 242, 242);//themeresources.xaml - Light
private void SetFlyoutBackBrush(Color color)
{
var brushKey = "SystemControlBackgroundChromeMediumLowBrush";
if (Application.Current.Resources.ContainsKey(brushKey))
{
var flyoutbackBrush = Application.Current.Resources[brushKey] as SolidColorBrush;
if (flyoutbackBrush != null) flyoutbackBrush.Color = color;
}
}
private void Checked(object sender, RoutedEventArgs e)
{
this.RequestedTheme = ElementTheme.Dark;
SetFlyoutBackBrush(_darkColor);
}
private void Unchecked(object sender, RoutedEventArgs e)
{
this.RequestedTheme = ElementTheme.Light;
SetFlyoutBackBrush(_lightColor);
}
Note This will affect all Flyouts and Pickers across application as they all use SystemControlBackgroundChromeMediumLowBrush.
I found no so nice solution for this problem, but it is easy and works :)
http://blog.kurpio.com/2016/04/19/perelki-uwp-2-flyout-w-commandbar-obejscie-buga/
You can set SystemControlBackgroundChromeMediumBrush as a brush of Grid in Flyout Content.
<AppBarButton Label="Szukaj"
Icon="Find">
<AppBarButton.Flyout>
<Flyout Placement="Bottom">
<Flyout.Content>
<Grid Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}"
Margin="-15"
Padding="15"
Width="285">
<TextBox Header="Szukaj:"
Width="175"
HorizontalAlignment="Left" />
<AppBarButton Label="Szukaj"
Icon="Find"
HorizontalAlignment="Right" />
</Grid>
</Flyout.Content>
</Flyout>
</AppBarButton.Flyout>
</AppBarButton>
...notice to set Margin and Padding of Grid to fill the Flyout.

WP 8.1 ToggleButton Change Icon when Checked / UnChecked

I have the following XAML code for Windows Phone 8.1 (non SilverLight):
<Grid>
<ToggleButton Name="TogBtn" VerticalAlignment="Center" HorizontalAlignment="Center" Checked="ToggleButton_OnChecked">
<SymbolIcon Symbol="play"></SymbolIcon>
</ToggleButton>
</Grid>
The output of the above code is:
How can I change the icon to a stop icon when the toggle button is checked and then back to play icon when unchecked?
I thought this would be easy to find through Google, but apparently not.
Please change your XAML to this:
<Grid>
<ToggleButton x:Name="TogBtn" HorizontalAlignment="Center" VerticalAlignment="Center" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked">
<SymbolIcon Symbol="Play"></SymbolIcon>
</ToggleButton>
</Grid>
And please add this to your .cs file:
private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
TogBtn.Content = new SymbolIcon(Symbol.Stop);
}
private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
TogBtn.Content = new SymbolIcon(Symbol.Play);
}
That should do the job!

Displaying a Progress Bar

I have an image control in my main page and the code is as follows:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel HorizontalAlignment="Left" Height="597" VerticalAlignment="Top" Width="440">
<Image x:Name="hinh1" Height="488" Stretch="Fill"/>
<ProgressBar Name="loading" Height="10" IsIndeterminate="True" Visibility="Collapsed"/>
</StackPanel>
</Grid>
and in code behind i have this code :
Uri hinh = new Uri
("http://taigamejar.net/wp-content/uploads/2014/01/Hinh-Anh-Dep-5.jpg", UriKind.Absolute);
hinh1.Source = new BitmapImage(hinh);
While waiting for the image to load, I want to call progress bar run to inform the user that it is loading. Once the the image has loaded, the progress bar should disappear. How can I do this?
If I were you, I would prefer to use , not ProgressBar.
So, I'll give
protected override void OnNavigatedTo(NavigationEventArgs e)
{
loading.IsActive = true;
Uri hinh = new Uri
("http://taigamejar.net/wp-content/uploads/2014/01/Hinh-Anh-Dep-5.jpg", UriKind.Absolute);
hinh1.Source = new BitmapImage(hinh);
hinh1.ImageOpened+=hinh1_ImageOpened; //loadingbar will be disappear when this triggered
}
private void hinh1_ImageOpened(object sender, RoutedEventArgs e)
{
loading.IsActive = false; //this will disable the progressring.
}
And XAML:
<StackPanel HorizontalAlignment="Left" Height="597" VerticalAlignment="Top" Width="400">
<Image x:Name="hinh1" Height="488" Stretch="Fill" ImageOpened="hinh1_ImageOpened"/>
<ProgressRing Name="loading" Height="109" IsActive="True" />
</StackPanel>
If you don't have WP8.1 SDK yet, you can get ProgressRing here: http://www.onurtirpan.com/onur-tirpan/english/windows-phone-english/using-progressring-in-windows-phone/