I have a page in a Windows Phone 8.1 app where I have a few components that should be able to have three different color states. They should either be red, blue or the current theme's foreground color.
Therefore, if my app is started using the Dark theme on the phone, and then the user steps out of the app and changes the Light theme, and steps in to my app again, I need to immediately change components that had the old theme's foreground color.
Since the components are supposed to change between different colors (where the theme's foreground color is just one of them) I can't set their Foreground to PhoneForegroundColor
in XAML
.
What I've done is to add a Resuming
event listener that does this:
myTextBlock.Foreground = new SolidColorBrush((Color)Application.Current.Resources["PhoneForegroundColor"]);
But... the Resuming
event is fired before the resources of Application.Current are updated, so I end up with the same color as before. If the user steps out again and in again, it'll work since Application.Current.Resources["PhoneForegroundColor"]
was updated at some point after the Resuming
event the previous time.
Question: When can I first read the updated Application.Current.Resources["PhoneForegroundColor"]
, since Resuming
doesn't seem to be the right place?
Question: Alternatively, is there a way for myTextBlock
to inherit another component's ForegroundColor (CSS-ish), so that I can change the myTextBlock.Foreground
programatically between Red/Blue/Inherit without having to mind changes to the Phone Theme within my app's lifecycle?
Any suggestions appreciated!
Regarding your first question: The "Resume process" isn't officially documented, but I figured out the following:
Resume gets called on the UI thread. As it is a void returning method, the caller will just continue, when it has an await inside. If you marshall something into the UI thread, it will be in the dispatcher queue and therefor run after the current task (resume).
So I just made this (and it works^^):
private async void App_Resuming(object sender, object e)
{
var x1 = new SolidColorBrush((Color)Application.Current.Resources["PhoneForegroundColor"]);
Debug.WriteLine(x1?.Color.ToString());
// Await marshalls back to the ui thread,
// so it gets put into the dispatcher queue
// and is run after the resuming has finished.
await Task.Delay(1);
var x2 = new SolidColorBrush((Color)Application.Current.Resources["PhoneForegroundColor"]);
Debug.WriteLine(x2?.Color.ToString());
}
Regarding your second question: You could introduce a "ValueProvider" in your app.xaml, that registers for the resume event and just provides a dependency property with the current color.
You will still have to set that on any TextBlock you want to use that in, but at least directly in XAML. This might work for styles too, but did not try that.
Sample implementation....
Provider:
public class ColorBindingProvider : DependencyObject
{
public ColorBindingProvider()
{
App.Current.Resuming += App_Resuming;
}
private async void App_Resuming(object sender, object e)
{
// Delay 1ms (see answer to your first question)
await Task.Delay(1);
TextColor = new SolidColorBrush((Color)Application.Current.Resources["PhoneForegroundColor"]);
}
public Brush TextColor
{
get { return (Brush)GetValue(TextColorProperty); }
set { SetValue(TextColorProperty, value); }
}
public static readonly DependencyProperty TextColorProperty =
DependencyProperty.Register("TextColor", typeof(Brush), typeof(ColorBindingProvider), new PropertyMetadata(null));
}
App.xaml:
<Application.Resources>
<local:ColorBindingProvider x:Name="ColorBindingProvider" TextColor="{StaticResource PhoneForegroundBrush}" />
</Application.Resources>
MainPage.xaml:
<TextBlock Text="Hey ho let's go" Foreground="{Binding TextColor, Source={StaticResource ColorBindingProvider}}" />
In Windows Phone 8.1 you are able to determine the selected theme via Application.Current.RequestedTheme
witch will return a value of the enum Windows.UI.Xaml.ApplicationTheme
.
example:
public static string GetImagePath(){
// if the background color is black, i want a white image
if(Application.Current.RequestedTheme == ApplicationTheme.Dark)
return "ms-appx:///Assets/img_light.jpg";
// if the background color is white, i want a dark image
return "ms-appx:///Assets/img_dark.jpg";
}
side note: you are even able to change the selected theme with Application.Current.RequestedTheme
more details: https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.application.requestedtheme
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With