简体   繁体   中英

wpf Access to 3rd party Themes and Skins via ResourceDictionary

I'm creating a WPF Revit Addin. For this I'd like to use some 3rd party controls for extra UI functionality and for their styles ( see ModernWpf ])

Within a 'normal' WPF application it all works fine: I add the library (nuget) and added the themes resouces to the app.xaml 's ResourceDictionary.MergedDictionaries .

<Application.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <ui:ThemeResources />
      <ui:XamlControlsResources />
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

Adding (for example) a DropDownButton control to a page and running the WPF app results in a working and styled DropDownButton.

DropDownButton with styling

In my Revit Addin this doesn't work somehow. Since there is no app.xaml , I tried to add the resources at different places (Window, Page, UserControl, my theme resource MainTheme.xaml , ... The control itself is shown and the dropdown action works, but there is no styling.

DropDownButton without styling

The ModernWpf.dll and ModernWpf.Controls.dll are copied to the Revit Addins folder, and these dll's hold the resources (as seen with DotPeek), so these should be available somehow.

DotPeek on ModernWpf.dll

What am I missing / how can I fix this?

Thanks in advance, Michel

As you pointed out, in Revit add in there is no app.xaml so no assembly wide resources either, this is because Revit add in is a class library, not a proper WPF application. You can check out this question and take one of the approaches. In my add-ins, I fixed this issue like this:

Create xaml file with resource dictionary, for example "Resources.xaml" (to easily create WPF things inside class library, check out this question )

Create your global resources in "Resources.xaml"

Create this class. Replace *name of your project* with name of your project.

public class SingletonResources : ResourceDictionary
    {
        private static ResourceDictionary? inst;

        public SingletonResources()
        {
            if (inst is null)
            {
                var uri = new Uri("/*name of your project*;component/Themes/Resources.xaml", UriKind.Relative);
                inst = (ResourceDictionary)System.Windows.Application.LoadComponent(uri);
            }

            MergedDictionaries.Add(inst);
        }
    }

Then in every control where you want to be able to access "Resources.xaml", inside of control resources include SingletonResources. Like this:

<Window.Resources>
        <revitPluginUi:SingletonResources>
        </revitPluginUi:SingletonResources>
</Window.Resources>

Now you can access all resources from "Resource.xaml" inside window.

IDE autocompletion for resource keys will not work.

Important note: if you need to create local resources for control, and you defined SingletonResources you need to define local resources inside SingletonResources tag. Like this:

<Window.Resources>
        <revitPluginUi:SingletonResources>
            <SolidColorBrush x:Key="MyLocalBrush"/>
        </revitPluginUi:SingletonResources>
</Window.Resources>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM