In a Windows Store App, I am unable to use a resource in one resource dictionary as the value of a property setter in a style of a second resource dictionary via a StaticResource binding.
Here is an example of what I'm trying to do:
Dictionary1.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="SomeBrush" Color="Black" />
</ResourceDictionary>
Dictionary2.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="SomeStyle" TargetType="Button">
<Setter Property="Foreground" Value="{StaticResource SomeBrush}" />
</Style>
</ResourceDictionary>
App.xaml
<Application
x:Class="TestApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Common/StandardStyles.xaml"/>
<ResourceDictionary Source="Common/Dictionary1.xaml"/>
<ResourceDictionary Source="Common/Dictionary2.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
No matter what I do, this does not work. The app will not launch, instead throwing an unhandled exception to the effect of "a resource with key 'SomeBrush' cannot be found".
I've tried changing the order in App.xaml, playing with nested merged dictionaries, etc.
I have managed to get it to work by doing this, but this is not an option:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="SomeStyle" TargetType="Button">
<Setter Property="Foreground" Value="{StaticResource SomeBrush}" />
</Style>
</ResourceDictionary>
At run time, App.Resources.MergedDictionaries is cleared and various resource dictionaries are dynamically loaded depending on various conditions. Both Dictionary1.xaml and Dictionary2.xaml are loaded independently of each other, and may contain different resources depending on those conditions, therefore merging them in this manner is not an option. They must be included in App.xaml at design time in order to support.... design.
Does anyone have any idea what is going on here? Is this a bug?
Thanks!
I believe I understand what's occurring here, I'll attempt to explain my view, hopefully it will make some sense.
From what I can see, after playing around and being able to replicate the issue you are seeing, it looks to me as though using the StaticResource keyword means that the key it's referring to needs to be available in the "scope" of the ResourceDictionary.
This would explain why your second attempt worked, because you have merged Dictionary1.xaml with Dictionary2.xaml, hence SomeBrush could be considered "in scope" and it would work.
Evidently, in the first scenario, the key defined in Dictionary1.xaml is considered "out of scope" for Dictionary2.xaml. But it would be considered "in scope" for the application.
I am basing a lot of this on what I have observed, but I have also found the following sentence in the ResourceDictionary and XAML resource references page on MSDN:
Within the scope of the ResourceDictionary, the dictionaries are checked for key uniqueness. However, that scope does not extend across different items in MergedDictionaries.
I had today a similar problem with a Universal App Project. The problem was, that the merged dictionaries need a Source-path with the ms-appx-protocol.
<ResourceDictionary Source="ms-appx:///Common/StandardStyles.xaml"/>
...
Does it solves your problem yet?
Related
I'm curious is there more convenient way to use themes in Xamarin forms.
Known way is add Colors into ResourceDictionary in App.xaml:
<Color x:Key="BackgroundColorDark">#111111</Color>
<Color x:Key="BackgroundColorLight">#ffffff</Color>
and then specify it on element like this:
<Button BackgroundColor="{AppThemeBinding Light={StaticResource DarkPageBackgroundColor},
Dark={StaticResource LightPageBackgroundColor}}" ... >
So my question is there possibility to do it in different way? I have reaaly lots of buttons for example, and I don't want to specify everywhere for each of those buttons that it has to use this color for light theme and that for dark. I want to specify it like: Hey Button, your background color is "ButtonBackgroundColor" and its value depends on current theme, which itself is set in two different ResourceDictionaries, like this:
<ResourceDictionary x:Name="Dark">
<Color x:Key="ButtonBackgroundColor">#000000</Color>
</ResourceDictionary>
<ResourceDictionary x:Name="White">
<Color x:Key="ButtonBackgroundColor">#ffffff</Color>
</ResourceDictionary>
You can use a ButtonStyle for different Buttons
<Color x:Key="LightPrimaryColor">WhiteSmoke</Color>
<Color x:Key="LightSecondaryColor">Black</Color>
<!-- Dark colors -->
<Color x:Key="DarkPrimaryColor">Teal</Color>
<Color x:Key="DarkSecondaryColor">White</Color>
<Style x:Key="ButtonStyle"
TargetType="Button">
<Setter Property="BackgroundColor"
Value="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}" />
<Setter Property="TextColor"
Value="{AppThemeBinding Light={StaticResource LightSecondaryColor}, Dark={StaticResource DarkSecondaryColor}}" />
</Style>
And in Xaml for a Button add Style
<Button Text="MORE INFO"
Style="{StaticResource ButtonStyle}" />
Info here https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/theming/system-theme-changes
I use ButtonStyle and made one ButtonStyleA for other Buttons that i want to show in an other way
The answer from Bas H is correct. You should use styles in most scenarios. You can also even use style implicitly, meaning they will be applied by default on all controls of the target type.
<Style TargetType="Button">
<Setter Property="BackgroundColor"
Value="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}" />
<Setter Property="TextColor"
Value="{AppThemeBinding Light={StaticResource LightSecondaryColor}, Dark={StaticResource DarkSecondaryColor}}" />
</Style>
// The backgroundcolor and textcolor are applied by default now.
<Button Text="MORE INFO"/>
Agree with comments above, think that most people miss that you can bind to static colours within the style inside the resource dictionary. Very useful when you want to change theme colours, one up is apples to all styles.
I do this but I also allow users to choose colours which i save in a database column, onload of the app I'll set the value in the resource dictionary in code ;)
I am facing a problem when I try to load a resource style from file to a UIElement.
My Resource file contains a copy of ToggleSwitch's default style, I changed just some colors.
I tried the following Resource references:
<Page.Resources>
<ResourceDictionary x:Key="GreenToggleResourceDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="GreenToggleSwitch.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
And my ToggleSwitch looks like this but it won't use the style in the referenced resource "GreenToggleSwitch.xaml":
<ToggleSwitch x:Name="ToggleSwitch"
Style="{StaticResource GreenToggleSwitchStyle}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Toggled="ToggleSwitch_Toggled"
</ToggleSwitch>
This is the GreenToggleSwitch.xaml, it's pretty much the ToggleSwitch default template:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CUE">
<x:Double x:Key="ToggleSwitchOnStrokeThickness">0</x:Double>
<Style TargetType="ToggleSwitch" x:Key="GreenToggleSwitchStyle">
.
.
.
</Style>
</ResourceDictionary>
This code won't work, because of the Style 'GreenToggleSwitch' that I want to use.
How has the code to be like to work?
Basically I want to change the blue coloring around the toggle thumb(/knob) to green. If I put the code from my Resource file into my MainPage.xaml, it will work.
Appreciate your help,
Viktor
Right, a resource dictionary isn't a style. What is the x:Key property of the style you want? Use that. If it's x:Key="Planxty", use Style="{StaticResource Planxty}". If it's x:Key="ImALittleTeapot", use Style="{StaticResource ImALittleTeapot}".
If it doesn't have a key, it's the implicit style and it should apply without any further effort on your part.
Secondly, you should merge the dictionary you're loading into the dictionary in your window/page/usercontrol/whatever.
Like so:
<Page.Resources>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="GreenToggleSwitch.xaml"/>
</ResourceDictionary.MergedDictionaries>
</Page.Resources>
Update
GreenToggleSwitchResource isn't defined anywhere. The XAML parser will not try to guess your intent when you throw weird random strings at it. It will say "Dammit, Jim, I'm a parser, not a parapsychologist!"
Use the identifier that you defined. This is programming. We call things by the identifiers we give them. You called it GreenToggleSwitchStyle. So that's how you refer to it.
<ToggleSwitch x:Name="ToggleSwitch"
Style="{StaticResource GreenToggleSwitchStyle}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Toggled="ToggleSwitch_Toggled"
</ToggleSwitch>
I don't know what you're getting at with all the theme stuff and you didn't say, so I didn't address that.
I have a few pages and want that they use one style. See in images, for example. as you can see all three pages have static styled header. So how i can do it?
Sorry if the question is easy, it's in the evening and i can't think very clear, and been working really hard...
I tried setting Template, but i keep getting an exception, that i cannot use templating for UserControl...
Why can't using like following?
<phone:PhoneApplicationPage.Style>
<Style TargetType="phone:PhoneApplicationPage">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="phone:PhoneApplicationFrame">
<StackPanel Background="Black">
<Border Height="100" Width="100" Background="Red"/>
<ContentPresenter />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</phone:PhoneApplicationPage.Style>
You could create a UserControl that includes a StackPanel, with a horizontal orientation, then add two controls inside the StackPanel, maybe an Image and a TextBlock, add margins as required, add colours as required. Once your UserControl is defined, add this UserControl to all the pages what you want to have the same look and feel. You might even be able to move this UserControl to a base page and derive your pages from this base page.
Hope this helps.
I would like to setup some default fonts as static resource within my App. Similarly with some colors.
Do I just use a string (defined as an applicationResource (in App.xaml) or can I actually define a FontFamily and a Color within here.
thanks
You could define an implicit style to set a default color and font family to use for all TextBlocks like this:
<Application.Resources>
<ResourceDictionary>
<Color x:Key="MySpecialColor">#F4811F</Color>
<SolidColorBrush x:Key="MySpecialColor" Color="{StaticResource MySpecialColor}" />
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource MySpecialColorBrush}" />
<Setter Property="FontFamily" Value="Comic Sans" />
</Style>
</ResourceDictionary>
</Application.Resources>
You could then adjust as necessary for specific TextBlocks and add implict styles for other controls if you need to.
Read more at http://www.windowsphonegeek.com/articles/Windows-Phone-7-Mango-Implicit-Styles
You can also use the color or the brush as you need elsewhere, either in XAML or code:
(Color)App.Current.Resources["MySpecialColor"];
I'm trying to design some UserControl classes in Blend 3. I want parts of them to be "collapsed" when created at runtime, but I want to be able to edit their component parts without fiddling with code every time I want to build.
It works with sample datasources, as the following example illustrates. But it doesn't appear to work with other properties... or am I doing something wrong?
With a sample data source SDS_AIVertexAction We can do this in Expression Blend:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
...>
<Grid x:Name="LayoutRoot"
d:DataContext="{Binding Source={StaticResource SDS_AIVertexAction}}" >
...
</Grid>
But it does not seem to be possible to do this:
<Label Content="{Binding Name}" Visibility="Collapsed" d:Visibility="Visible" />
I realise I could change visibility "on loaded" but I'd really rather not type all that guff every time I make a control like this. Does someone know a secret that lets us do this?
Well, here's a guess.
The d: namespace is for stuff that is respected at design time but ignored at runtime. So we want to set the visibility somehow within the d: namespace where it overrides visibility set for runtime.
Inline styles override styles set globally or via StaticResource, so I'd suggest doing this (from memory--don't just copy and paste it, understand the concept):
<UserControl.Resources>
<Style x:Key="invisible" TargetType="Label">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
</UserControl.Resources>
<!-- ... -->
<Label Style="{StaticResource invisible}" d:Visibility="Visible" />