I like my Navigation Bars to have different BarBackgroundColor & BarTextColor. It worked fine so far like follows. But now I have problems to alter Colors with regard to OS light mode and dark mode. I thought a solution using "AppThemeBinding" would be logical. I use this concept for all view types. But here it throws an - System.Reflection.TargetInvocationException - I cannot solve. The problem seems to be "Specific cast ist not valid"
Please assist. I searched for solutions in different places. Maybe my thinking/concept is wrong?
//Solution without OS light/dark mode adaption--
//App.xaml.cs
var page = new x_temp.TestStartPage(); //content page MainPage = new NavigationPage(page) { Style = (Style)Application.Current.Resources["NavBarStyle"] };
//App.xaml
<Style TargetType="NavigationPage" x:Key="NavBarStyle"> <Setter Property="BarBackgroundColor"> <Setter.Value> <OnPlatform x:TypeArguments="Color" > <On Platform="Android" Value="#DBE5FA"/> <On Platform="iOS" Value="#FFFFFF"/> </OnPlatform> </Setter.Value> </Setter> </Style>
//Attempt with OS light/dark mode adaption
<Style TargetType="NavigationPage" x:Key="NavBarStyle"> <Setter Property="BarBackgroundColor"> <Setter.Value> <OnPlatform x:TypeArguments="Color" > <On Platform="Android" Value="_{AppThemeBinding Light=#DBE5FA, Dark=#584F4F, Default=#DBE5FA}"_/> <On Platform="iOS" Value="_{AppThemeBinding Light=#FFFFFF, Dark=#584F4F, Default=#FFFFFF}"_/> </OnPlatform> </Setter.Value> </Setter> </Style>
The Xaml you pasted suppose that the OnPlatform
object is the target of the Binding to Color, and then the OnPlatform
returns the right Color depending on the Platform.
Unfortunately, that doesn't work because OnPlatform
is not a BindableObject
and can't be the target of a Binding.
So your code should be
<Style TargetType="NavigationPage" x:Key="NavBarStyle"> <Setter Property="BarBackgroundColor"> <Setter.Value> <OnPlatform x:TypeArguments="BindingBase" > <On Platform="Android" Value="{AppThemeBinding Light=Red, Dark=#111111, Default=#111111}"/> <On Platform="iOS" Value="{AppThemeBinding Light=#FFFFFF, Dark=#584F4F, Default=#FFFFFF}"/> </OnPlatform> </Setter.Value> </Setter> </Style>
However, the color does not display as expected , it still shows the default color(blue).
As a workaround , we could set it in code behind.
<Style TargetType="NavigationPage" x:Key="AndroidNavBarStyle"> <Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light=#DBE5FA, Dark=#584F4F, Default=#DBE5FA}"> </Setter> </Style> <Style TargetType="NavigationPage" x:Key="iOSNavBarStyle"> <Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light=#FFFFFF, Dark=#584F4F, Default=#FFFFFF}"> </Setter> </Style>
string color = null; if(Device.RuntimePlatform == Device.Android) { color = "AndroidNavBarStyle"; } else if(Device.RuntimePlatform == Device.iOS) { color = "iOSNavBarStyle"; } MainPage = new NavigationPage(page) { Style = (Style)Application.Current.Resources[color] };
Answers
Please ignore die underscores in the last code example. Those were added as I tried to put the text to italic.
The Xaml you pasted suppose that the
OnPlatform
object is the target of the Binding to Color, and then theOnPlatform
returns the right Color depending on the Platform.Unfortunately, that doesn't work because
OnPlatform
is not aBindableObject
and can't be the target of a Binding.So your code should be
However, the color does not display as expected , it still shows the default color(blue).
As a workaround , we could set it in code behind.
Xaml
Code hebind
Refer to https://stackoverflow.com/a/41829242/8187800.
@ColeX Thanks for your efforts. I tried and adapted the second solution and it works for me. You were of great help!