1

For a Revit plugin I'm building a WPF dialog, with a view, logic, and now some styling.

Very quickly I came to the conclusion that putting all my styling in the is really messy (it just means I'm scrolling through my XAML half of my time). So I wanted to split my styling from my XAML code (like you would with HTML and CSS).

So I found out about the and how I should go about setting it up. I have my window, with this resource code:

    <Window.Resources>
    <local:LocationView x:Key="mainViewDataSource" />
    <FontFamily x:Key="Ubuntu">pack://application:,,,/Kalec.Enveo;component/src/Resources/Fonts/#Ubuntu</FontFamily>
    <FontFamily x:Key="FontAwesomeSolid">pack://application:,,,/Kalec.Enveo;component/src/Resources/Fonts/#Font Awesome 5 Free Solid</FontFamily>
    <FontFamily x:Key="FontAwesomeRegular">pack://application:,,,/Kalec.Enveo;component/src/Resources/Fonts/#Font Awesome 5 Free Regular</FontFamily>

    <ResourceDictionary x:Key="dictionary" Source="pack://application:,,,/Kalec.Enveo;component/src/WPF/Styles/Dictionary.xaml" />

</Window.Resources>

And my Dictionaries:

Dictionary.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary x:Key="MergedDictionaries">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Dictionaries/InputStyles.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

and InputStyles.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="SearchInputStyle" TargetType="{x:Type TextBox}">
    <Setter Property="Height" Value="30"/>
    <Setter Property="FontWeight" Value="Bold" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <Border CornerRadius="15" Background="White" BorderBrush="Transparent" x:Name="border">
                    <Grid>
                        <TextBox Text="{Binding Path=Text,
                                            RelativeSource={RelativeSource TemplatedParent}, 
                                            Mode=TwoWay,
                                            UpdateSourceTrigger=PropertyChanged}"
                             x:Name="textSource" 
                             Background="Transparent" 
                             Panel.ZIndex="2" />
                            <TextBox Text="{TemplateBinding Tag}" Background="{TemplateBinding Background}" Panel.ZIndex="1">
                                <TextBox.Style>
                                    <Style TargetType="{x:Type TextBox}">
                                        <Setter Property="Foreground" Value="Transparent"/>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value="">
                                                <Setter Property="Foreground" Value="Gray"/>
                                                <Setter Property="HorizontalContentAlignment" Value="Left"/>
                                                <Setter Property="VerticalContentAlignment" Value="Center"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </TextBox.Style>
                            </TextBox>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="BorderBrush" TargetName="border" Value="Red"/>
                        <Setter Property="Foreground" Value="Red" />

                    </Trigger>
                    <Trigger Property="IsFocused" Value="true">
                        <Setter Property="Foreground" Value="Blue" />
                        <Setter Property="BorderBrush" TargetName="border" Value="Blue"/>
                    </Trigger>
                    <DataTrigger Binding="{Binding Path=Text}" Value="">
                        <Setter Property="Text" Value="Vul een adres in"/>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The problem is that I can't seem to use the style on my textBox:

 <StackPanel Margin="10,10,0,0" Orientation="Vertical">
                <StackPanel Panel.ZIndex="10" Orientation="Horizontal" 
                    Name="SearchParameters" 
                    >
                    <TextBox Width="220" Style="{DynamicResource SearchInputStyle}"/>
                    <Button FontFamily="{StaticResource FontAwesomeSolid}" 
                        Content="&#xf019;" Foreground="#31B192" Grid.ColumnSpan="2" 
                        Style="{DynamicResource LocationImport}"
                        Margin="10, 0, 0, 0"/>
                </StackPanel>

I simply get the error that it could not be resolved. I looked at some solutions, and most of them tell me to include the ResourceDictionary in my App.xaml, but I don't have that file, because my project is a class library (it's a requirement for the plugin).

Can I even use Resource Dictionaries? Or is there some other way to seperate the styling or XAML in different files?

Martijn
  • 141
  • 1
  • 8

1 Answers1

0

I guess you got the correct ingredients but not the correct recipe.

Here's how its working for me: SampleWpfProject

I have a class library project which defines all my styles (ControlLibrary in the image) Here is one Button styles ResourceDictionary

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApp1">

    <Style x:Key="RedButton" TargetType="Button">
        <Style.Setters>
            <Setter Property="Background" Value="Red"/>
        </Style.Setters>
    </Style>

    <Style x:Key="GreenButton" TargetType="Button">
        <Style.Setters>
            <Setter Property="Background" Value="Green"/>
        </Style.Setters>
    </Style>
</ResourceDictionary>

Then Here's is the single point of contact for all individual styles. Dictionary.xaml (Note that this is using MergedDictionary)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApp1">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="./Styles/ButtonStyles.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Finally to use the Styles from ClassLibrary dll into my WpfApp project (after adding reference to it) we again use MergedDictionaries..!!

<Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/ControlLibrary;component/Dictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
Prateek Shrivastava
  • 1,877
  • 1
  • 10
  • 17
  • Nice answer, sorry i didn't see it before i found the duplicate – TheGeneral Feb 12 '20 at 21:56
  • @MichaelRandall - No problem :) – Prateek Shrivastava Feb 12 '20 at 21:58
  • Thanks, I missed using the MergedDictionaries again in my Window.Resources. I will try it and get back to you! – Martijn Feb 13 '20 at 08:26
  • I'm sorry but it's still not working. Also, the application I'm using the styles isn't a WPF app, it's a C# class library. – Martijn Feb 13 '20 at 18:44
  • @Martijn - That's the problem. You need to first add the project as WPF App. That adds all the relevant references (PresentationCore, WindowsBase etc) and also adds a thing in AssemblyInfo.cs if I am not mistaken. This allows proper compiling etc. Once you organize your project structure (delete app.config, app.xaml etc) You can then change the project type to ClassLibrary (thats what I did). – Prateek Shrivastava Feb 13 '20 at 21:38