Answered by:
What is so special about generic.xaml?

Question
-
Hi,
If I place all my styles under generic.xaml, other user controls don't seem to have any problems accessing it. However, I would like to keep all my brushes under brushes.xaml. Further, I would like to keep my resouce dictionaries under a folder called Resources (and not Themes as used by generic.xaml).
The problem is, when I store my brushes under brushes.xaml, they are not accessible to any of my user controls. However, if I pull the resource dictionary in app.xaml, as shown below, it seems to work.
Code Block<ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/Resources/Brushes.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary>I compared the settings for generic.xaml and Brushes.xaml. They seem to be exactly the same.
Why does it work with generic.xaml without using the above trick?
Thank you in advance for your help.
Regards,
Peter
Friday, December 28, 2007 3:37 AM
Answers
-
Peter wrote:
Is "Themes\generic.xaml" hardcoded in WPF engine itself (which is hard to believe) or is this a functionality of VS 2008?
Yes, it's hardcoded, and this functionality has nothing to do with Visual Studio 2008, it's the implementation detail of WPF stack within .Net Framework 3.0/3.5
Every resource dictionaries under "Themes" directory under your project will be "compiled"(this compilation process is done by msbuild and the custom build tasks) into BAML representation, and those BAML files will be treated as resources files for the finally compiled assemblies.
In order to discover those resource dictionaries, you need to mark the compiled assemblies using custom attribute ThemeInfoAttribute, this attribute has two properties GenericDictionaryLocation and ThemeDictionaryLocation, GenericDictionaryLocation property tells where is the generic resource dictionary aka generic.xaml is located, ThemeDictionaryLocation property tells where is the theme aware resource dictionaries aka Aero.NormalColor.xaml etc are located. Both of those properties alongside with ThemeInfoAttribute gives WPF's style/theme mechanism enough information about where the style/theme associated with a particular type is located.
Themed assemblies (assemblies marked with ThemeInfoAttribute attribute) is a mechanism in WPF for authoring custom control library, and it to some extent gives developers more flexibility without thinking about how to locate and load the styles associated with the custom control types, and this mechanism is also used internally by WPF to implement the PresentationFramework assemblies.
Another benefit of themed assemblies is that you can use themed assembly to define resource-only or shared resource assembly, because the resource dictionaries within the themed assemblies will be loaded only once, this can give much more benefits than the ResourceDictionary.MergedDictonaries mechanism, I have a sample at hand, you can refer to it at the following link:
http://www.cnblogs.com/Files/sheva/SharedResourcesDemo.zip
Hope this helpsTuesday, January 1, 2008 4:45 AM -
You can use the following code to enumerate over the resource dictionaries defined in a given assembly:
public class XamlResourceCollection : ObservableCollection<XamlResourceItem>
{
public XamlResourceCollection(Assembly assembly)
{
foreach (String resourceName in assembly.GetManifestResourceNames())
{
if (resourceName.ToLower().EndsWith(".g.resources"))
{
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
using (ResourceReader reader = new ResourceReader(stream))
{
foreach (DictionaryEntry entry in reader)
{
if (entry.Key.ToString().ToLower().EndsWith(".baml"))
{
XamlResourceItem item = new XamlResourceItem(entry.Key.ToString(), assembly.FullName);
this.Add(item);
}
}
}
}
}
}
}
}
public class XamlResourceItem
{
private String resourceName;
private Uri resourceUri;
public XamlResourceItem(String resourceName, String containingAssemblyName)
{
this.resourceName = Path.ChangeExtension(resourceName, "xaml").ToLower();
this.resourceUri = new Uri("/" + containingAssemblyName + ";component/" + resourceName, UriKind.RelativeOrAbsolute);
}
public String ResourceName
{
get { return resourceName; }
}
public Uri ResourceUri
{
get { return resourceUri; }
}
}
Hope this helpsThursday, January 17, 2008 8:32 AM
All replies
-
Basically Themes\generic.xaml is the resource file that the WPF will load auto matically for Custom controls mainly....
something like this
http://www.cubido.at/Blog/tabid/176/EntryID/81/Default.aspxFriday, December 28, 2007 10:07 PM -
generic.xaml is special because WPF makes it a special case for any custom controls with generic themes
WPF's style lookup mechanism will automatically pick up the styles defined in the generic.xaml file. If you want to apply themes in accordance with the system theme, you can create Aero.NormalColor.xaml, Classic.xaml, Luna.Homestead.xaml, Luna.Metallic.xaml, Luna.NormalColor.xaml, Royale.NormalColor.xaml files respectively for each themes available under different version of Windows.
Hope this helpsMonday, December 31, 2007 4:48 AM -
Hi,
Thank you all for your help.
Can you explain this further? Is "Themes\generic.xaml" hardcoded in WPF engine itself (which is hard to believe) or is this a functionality of VS 2008? I would imagine while building the assembly, VS 2008 must insert some special instructions for WPF to recognize "Themes\generic.xaml" to be the fallback file. However, when I looked at the .csproj file, I did not see anything that indicates that "Themes\generic.xaml" must be treated specially (compared to other custom resource dictionaries).
Regards,
Peter
Monday, December 31, 2007 9:33 PM -
Peter wrote:
Is "Themes\generic.xaml" hardcoded in WPF engine itself (which is hard to believe) or is this a functionality of VS 2008?
Yes, it's hardcoded, and this functionality has nothing to do with Visual Studio 2008, it's the implementation detail of WPF stack within .Net Framework 3.0/3.5
Every resource dictionaries under "Themes" directory under your project will be "compiled"(this compilation process is done by msbuild and the custom build tasks) into BAML representation, and those BAML files will be treated as resources files for the finally compiled assemblies.
In order to discover those resource dictionaries, you need to mark the compiled assemblies using custom attribute ThemeInfoAttribute, this attribute has two properties GenericDictionaryLocation and ThemeDictionaryLocation, GenericDictionaryLocation property tells where is the generic resource dictionary aka generic.xaml is located, ThemeDictionaryLocation property tells where is the theme aware resource dictionaries aka Aero.NormalColor.xaml etc are located. Both of those properties alongside with ThemeInfoAttribute gives WPF's style/theme mechanism enough information about where the style/theme associated with a particular type is located.
Themed assemblies (assemblies marked with ThemeInfoAttribute attribute) is a mechanism in WPF for authoring custom control library, and it to some extent gives developers more flexibility without thinking about how to locate and load the styles associated with the custom control types, and this mechanism is also used internally by WPF to implement the PresentationFramework assemblies.
Another benefit of themed assemblies is that you can use themed assembly to define resource-only or shared resource assembly, because the resource dictionaries within the themed assemblies will be loaded only once, this can give much more benefits than the ResourceDictionary.MergedDictonaries mechanism, I have a sample at hand, you can refer to it at the following link:
http://www.cnblogs.com/Files/sheva/SharedResourcesDemo.zip
Hope this helpsTuesday, January 1, 2008 4:45 AM -
Hello Marco,
Thank you for your help.
If I understanding you right, *any* resource dictionary file under "Themes" directory will be automatically compiled and added as a resource, not just generic.xaml. Is this correct?
Also, if I have to programatically enumerate through all the themed resources within an assembly, how would I do that? If I knew it was "generic.xaml," I could have used the source as "assembly;component/themes/generic.xaml." However, not knowing the actual file name(s), can I use "assembly;component/themes/*" ?
Apprecitate your help in enlightening me.
Regards,
Peter
Wednesday, January 16, 2008 9:05 PM -
You can use the following code to enumerate over the resource dictionaries defined in a given assembly:
public class XamlResourceCollection : ObservableCollection<XamlResourceItem>
{
public XamlResourceCollection(Assembly assembly)
{
foreach (String resourceName in assembly.GetManifestResourceNames())
{
if (resourceName.ToLower().EndsWith(".g.resources"))
{
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
using (ResourceReader reader = new ResourceReader(stream))
{
foreach (DictionaryEntry entry in reader)
{
if (entry.Key.ToString().ToLower().EndsWith(".baml"))
{
XamlResourceItem item = new XamlResourceItem(entry.Key.ToString(), assembly.FullName);
this.Add(item);
}
}
}
}
}
}
}
}
public class XamlResourceItem
{
private String resourceName;
private Uri resourceUri;
public XamlResourceItem(String resourceName, String containingAssemblyName)
{
this.resourceName = Path.ChangeExtension(resourceName, "xaml").ToLower();
this.resourceUri = new Uri("/" + containingAssemblyName + ";component/" + resourceName, UriKind.RelativeOrAbsolute);
}
public String ResourceName
{
get { return resourceName; }
}
public Uri ResourceUri
{
get { return resourceUri; }
}
}
Hope this helpsThursday, January 17, 2008 8:32 AM -
Marco,
Thank you very much for your help.
Regards,
Peter
Thursday, January 17, 2008 7:23 PM