Assembly-wide / root-level styles in WPF class library

后端 未结 7 2003
夕颜
夕颜 2021-01-30 06:28

I have a C# (2008/.NET 3.5) class library assembly that supports WPF (based on this article).
I\'ve created several windows, and am now attempting to create a common style

7条回答
  •  梦谈多话
    2021-01-30 07:30

    Here is a simple solution for sharing resources "module-wide" across a .NET class library. Importantly, it seems to robustly preserve the XAML Designer display capabilities and behaviors in Visual Studio.

    Start by adding a new C# class derived from ResourceDictionary as follows. An instance of this class will replace the default ResourceDictionary on each System.Windows.Control (or other ResourceDictionary-bearing component) in the class library that needs to see the shared resources:

    ComponentResources.cs:

    using System;
    using System.Reflection;
    using System.Windows;
    using System.Windows.Markup;
    
    namespace MyNamespace
    {
        [UsableDuringInitialization(true), Ambient, DefaultMember("Item")]
        public class ComponentResources : ResourceDictionary
        {
            static ResourceDictionary _inst;
    
            public ComponentResources()
            {
                if (_inst == null)
                {
                    var uri = new Uri("/my-class-lib;component/resources.xaml", UriKind.Relative);
                    _inst = (ResourceDictionary)Application.LoadComponent(uri);
                }
                base.MergedDictionaries.Add(_inst);
            }
        };
    }
    

    Be sure to replace MyNamespace and my-class-lib in the previous code snippet with (respectively) the namespace and assembly filename (without the '.dll' extension) from your own project:

    Add a new ResourceDictionary XAML file to your class library project. Unlike as for 'Application' assemblies, there is no option for this in the Visual Studio UI, so you'll have to do it manually. This will contain the resources you want to share across the whole class library:

    $(ProjectDirectory)\Resources.xaml:

    
    
        
    
        
        
    
    
    

    Set the Build Action to "Page" and be sure the File Properties information looks like this:

    Finally, go to the XAML files in the project that need to reference the shared resources, and replace the default ResouceDictionary (typically, on the Resources property of the XAML root element) with a ComponentResources instance. This will hold each component's private resources, and as you can see in the code above, the constructor attaches the module-wide shared singleton ResourceDictionary as a "merged dictionary." Do this for every control that should see the shared resources, even those that have no private resources of their own. Of course, you can also skip this step to exclude certain controls from sharing as needed. For example:

    
    
        
            
                
                
            
        
    
        
        
            
        
    
    
    

    As advertised, it works great, including in the XAML Designer...

提交回复
热议问题