What is the best way to share common resources within a shared Windows Phone/Store app? - windows-phone

Migrating from individual Windows Phone and Windows Store (Desktop) apps to the new shared app paradigm, I'm having trouble sharing resources between them. For example, specifically, when I want to style the Pivot control (and its children items), I try to place the style and its features into the central App.xaml file and I get the error that the Pivot control (and its children items) are not found in the Windows.Phone.Controls(.Primitives) assembly, when I know they ARE described there.
However, when I place the same style in-line within the page OR in a separate resource dictionary in the Windows.Phone folder section, the style works. This seems to defeat the purpose of having an all-in-one app system that should share common resources. After trudging through multiple SO answers, forums and the MSDN system, I don't find a straight-forward solution to this problem.
What is the proper way to share common resources between the Windows Phone and Windows Store sections of the new shared Windows app solution???

First, the reason why the Pivot control is not defined in the App.xaml file resources is that it is SPECIFIC to the Windows Phone system - it is NOT defined in Windows Store the same way (Windows Store apps use a Hub control, which is very similar). SO, the way to share resources appropriately between the two sections of a Shared Windows Phone/Store app is to:
1) create commonly named resource dictionary files in both folder systems, but ONLY where these components will be different from Phone to Store implementations (Pivot vs. Hub is an example). E.g., create a StylesResources.xaml dictionary in BOTH folder systems (Phone and Store).
2) create truly SHARED resource dictionaries in the "Shared" folder system. E.g., create a StringResources.xaml dictionary ONCE in the MyApp.Shared folder system.
3) do NOT place any resources directly into the App.xaml file in the MyApp.Shared folder system - instead, MERGE all your shared and non-shared dictionaries there, like this:
<Application
x:Class="MyApp.App"
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="MyApp">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ColorResources.xaml" />
<ResourceDictionary Source="ControlResources.xaml" />
<ResourceDictionary Source="DimensionResources.xaml" />
<ResourceDictionary Source="FontResources.xaml" />
<ResourceDictionary Source="StyleResources.xaml" />
<ResourceDictionary Source="StringResources.xaml" />
<ResourceDictionary Source="TemplateResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
In the example above, only StringResources.xaml and ColorResources.xaml are in the MyApp.Shared folder... the rest are duplicate dictionary names created in BOTH the Phone and Store folder systems.
When the system compiles for Phone, it uses the merged Phone dictionaries and it uses the Store dictionaries when it compiles for that system. This way, you don't have to repeat the declarations in the individual pages - you can share COMMON resources and define individually ONLY the resources that will be different from Phone to Store.
(This makes sense, because, for example, your margins and fonts are likely to be different when building for Pone vs. Store and the reverse.)

Related

Maui using style.xaml from a class libary

I've created 2 projects in Maui. The first is a class library with a resource dictionary in it. The second is the actual app I want to use the resource dictionary so I tried referencing it in the App.xaml.
I have setup the GuiLibrary as a dependency of the app that needs to use it
All attempts have this at the top in the application section of the App.xaml
xmlns:gui="clr-namespace:AppGuiLibrary;assembly=AppGuiLibrary"
I've tried the following different combinations to no success.
<ResourceDictionary Source="AppGuiLibrary/Styles.xaml"/>
<ResourceDictionary Source="/AppGuiLibrary;component/Styles.xaml"/>
<ResourceDictionary Source="/gui;component/Styles.xaml"/>
The Styles.xaml is a Maui.Xaml content type.
The error I got for all of them is
Resource X not found
Does anyone know what I'm missing to get this to work?

Setup a WinRt App with a reference to a Class Library which has a reference to a Class Library

So my project structure is as follows:
I have a Class Library that I am using made by XamlToolkit, since I had to tweak a certain handler I now have an implementation of my own.
This implementation is added as a reference to my BaseApp Class Library which contains Resource Dictionaries and some Code files for controls and such.
This BaseApp library builds into a Dll fine and using the "Generate library layout" option under Build options most issues got solved.
Now in the main WinRt app i have a reference to the BaseApp library and I try to merge the styles into the app as followed:
<Application.Resources>
<ResourceDictionary Source="ms-appx:///BaseApp/CoreFile.xaml" />
</Application.Resources>
This leaves me with the following error:
An error occurred while finding the resource dictionary "ms-appx:///BaseApp/CoreFile.xaml"
My first question would be, why is this not working? The source declaration should be no problem.
The second question would be, is it even possible to do something such as Class Library to Class Library to WinRt App?
Edit:
In a WinRT project you normally use a Source such as "/Folder/File.xaml". Like Kristian says you need to use the ms-appx:// syntax to reference another project (such as my class library).
The missing key is that in the Class library however you need to use the ms:appx// for all the source declarations to combine the files into 1 resource dictionary like we did in the CoreFile
It is possible to reference class library A in class library B, and then reference class library B in WinRT project. There should be no problem. But if you want to use code from A in WinRT project, then your WinRT project need to reference A too.
If CoreFile.xaml is in the root directory of the BaseApp class library then your code should work but instead you need to write like this in App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///BaseApp/CoreFile.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
I never used the Generate library layout option and never got any problems, so I think this may be not needed, to prevent errors.

MergedDictionaries outside the primary project

I have a solution with 2 projects. First is the primary application, the second has controls in it. In the Generic.xaml, in a Silverlight project, one would do
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyLibNamespace;component/Themes/SomeFolder/MyControl.xaml" />
</ResourceDictionary.MergedDictionaries>
This doesn't seem to work in a Windows Store application class library. ReSharper wants the filepath to be "/Themes/SomeFolder/MyControl.xaml" but I still get a XamlParseException: Failed to assign to property 'Windows.UI.Xaml.ResourceDictionary.Source'. [Line: 7 Position: 36]
There's no such thing as a "Xaml file within other class/assembly" in WinRT. In other words: "EmbeddedResource" or "Resource" simply doesn't exist in a WinRT component (and yes this is a pain). This is also why \Themes\Generic.xaml is copied out into the output directory).
See answer here on msdn
If you have a dll named "CustomControl" with a ResourceDictionary named "Styles.xaml", the App.xaml should contain
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///CustomControls/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Can reproduce the same behavior if the ResourceDictionary Source is set to a XAML that is a UserControl. However, if the XAML file referenced is a dedicated ResourceDictionary, there is no problem accessing internal styles with the ms-appx:/// scheme, following the ms-appx:///PROJECT_NAME/PATH_TO_XAML.xaml pattern.
Any chance the ResourceDictionary can be separated from the UserControl, if that is the case?

Using RESX with Windows Phone 7 in XAML

I am currently making a basic Windows Phone 7 application for fun, and I am trying to store string (currently only those) values in a RESX file rather than embedding them all within the XAML files directly, or even adding code to manually insert the values.
In WPF, to use the property from the RESX file, you simply map the namespace that contains the RESX:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:resx="clr-namespace:Namespace.To.Your.Resx;assembly=SuppliedIfSeparate"
and then use it:
<TextBlock Text="{x:Static resx:Strings.AppTitle}" />
But, I tried, and I've read that x:Static is simply not supported by Silverlight, and by extension, not supported in WP7 (It appears that they have provided the means, but not direct access to x:Static (French) in Silverlight 5/Mango).
I found this post describing an "AppConverter" class that is manually created to leverage similar functionality and it is currently what I am doing. The gist of the post is to create a resource within your XAML page that uses the AppConverter class for pre-specified keys, and then using that to replace the x:Static with a binding.
<TextBlock Text="{Binding Source={StaticResource AppTitle},Converter={StaticResource ResourceRetriever}}" />
It works, but it's verbose and error prone compared to the WPF implementation (a lot of copying and pasting between pages, and even controls).
What is the current best practice for this situation?
MSDN How to: Build a Localized Application for Windows Phone

Custom Theme That Overrides Default Theme WP7

Is it possible to create a custom theme and have it used as the default theme?
Every example I can find anywhere says you can create custom themes by copying the ThemeResources.xaml and System.Windows.xaml files and including them as merged dictionaries in your app.
http://windowsphonegeek.com/articles/Creating-WP7-Custom-Theme-ndash-Basic-Theme-Implementation
Overriding themes in Windows Phone 7
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/CustomThemeResources.xaml" />
<ResourceDictionary Source="Resources/CustomThemeStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Then I've read some more that you need to include the brushes inside the styles file, so in CustomThemeStyles.xaml I have this.
http://www.windowsphonegeek.com/articles/Creating-WP7-Custom-Theme---Complex-Theme
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CustomThemeResources.xaml" />
</ResourceDictionary.MergedDictionaries>
It doesn't work... so I download the sample app and sure enough, every page that wants to have some color changed, like the background color, will set it on it's outer most component.
<Grid Background="{StaticResource PhoneBackgroundBrush}">
...
</Grid>
Is it possible to include custom themes that change the style/brushes/colors/etc of all the defaults without having to explicitly set them everywhere?
It is not possible in the current version of WP7 to have a new Style that changes the default one without explicitly set it via "x:Key":
Implicit Styles are a feature of Silverlight 4 (and WPF): Windows Phone 7 is based on Silverlight 3+(with a few Silverlight 4 features added). Since there’s no Implicit Styles in Silverlight 3 this mean that there is no way to use them in Windows Phone 7 as well.
For now you can:
Only override the default Brushes/Colors resources as explained in the first article that you pointed out. Note that all WP7 controls will change their colors. Note also that for some reason the default Background remains unchanged. This is a known issue with the current version of WP7 and probably will be fixed in the "Mango" update.
If you want to have any new Style/ControlTemplate you must use the "x:Key"/{StaticResource ...} approach as mentioned in the second article that you pointed out.
Finally, as Derek Lakin mentioned previously: hopefully this bug will get fixed in the Mango update!
If you create a resource dictionary and call it something like Reset.xaml that contains all of the standard brush resources. Put any custom resource styles/brushes into another resource dictionary (we'll call it Custom.xaml for now). In App.xaml include both of these resource dictionaries as shown here:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Reset.xaml"/>
<ResourceDictionary Source="Resources/Custom.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
In theory, this should be enough, but unfortunately it's not. For some reason (hopefully a bug that will get fixed in the Mango update) you also need to include the Reset.xaml in the Custom.xaml like this:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Reset.xaml"/>
</ResourceDictionary.MergedDictionaries>
Once you've done this, that should be it; you shouldn't need to do anything else.
With the release of Windows Phone Mango (7.1), the feature of merging XAML dictionary styles no longer works. Currently, you will have to change the application resource Brush color entry in the code-behind; preferably in constructor of App() in App.xaml.cs.
Example:
(App.Current.Resources["PhoneAccentBrush"] as SolidColorBrush).Color = Color.FromArgb(12, 12, 54, 145);
(App.Current.Resources["PhoneForegroundBrush"] as SolidColorBrush).Color = Colors.Green;
(App.Current.Resources["PhoneBackgroundBrush"] as SolidColorBrush).Color = Colors.Purple;
Hopefully in the WP8 SDK we will no longer need to do this workaround.