Search code examples
c#wpfxamldata-bindingdatacontext

Bind to a property in a ResourceDictionary


I have a Templates.xaml file in my project which contains the ResourceDictionary of styles.

I want to bind Direction of a DropShadowEffect to MyNamespace.MyPage.LightDirection. Currently I did this:

// MyPage.xaml.cs
/// <summary>
/// Direction of light source for shadows and gradients.
/// </summary>
public static double LightDirection => 45;
<!--Templates.xaml-->
<Style x:Key="ControlButtons" TargetType="{x:Type Button}">
    <Setter Property="Effect">
        <Setter.Value>
            <DropShadowEffect ShadowDepth="4" Direction="{Binding LightDirection}" Color="Black" Opacity="0.5" BlurRadius="4" />
        </Setter.Value>
    </Setter>
    <!--Other Setters-->
</Style>
<!--MyPage.xaml-->
<Page x:Name="MyPage"
      DataContext="{Binding ElementName=MyPage}">
      <!--MyPage as some other default attributes which I didn't write here-->
    <Grid>
        <Button x:Name="MyButton" Style="{StaticResource ControlButtons}">
            My Button
        </Button>
    </Grid>
</Page>

It works. The shadow direction is set to LightDirection and program runs normally. However, while debugging, debugger shows a binding error:

Cannot find governing FrameworkElement or FrameworkContentElement for target element.

What is my mistake? How should I prevent this error?


Solution

  • I suggest making a constant

    namespace MyNamespace
    {
        public class Constants
        {
            public static double LightDirection { get; set; }
        }
    }
    

    XAML

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:local="clr-namespace:MyNamespace">
        <Style x:Key="ControlButtons" TargetType="{x:Type Button}">
            <Setter Property="Effect">
                <Setter.Value>
                    <DropShadowEffect ShadowDepth="4"
                                      Direction="{x:Static local:Constants.LightDirection}"
                                      Color="Black"
                                      Opacity="0.5" 
                                      BlurRadius="4" />
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
    

    Or declare constant directly in XAML

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:local="clr-namespace:MyNamespace"
                        xmlns:sys="clr-namespace:System;assembly=mscorlib" >
        <sys:Double x:Key="LightDirection">45.0</sys:Double>
        <Style x:Key="ControlButtons" TargetType="{x:Type Button}">
            <Setter Property="Effect">
                <Setter.Value>
                    <DropShadowEffect ShadowDepth="4"
                                      Direction="{StaticResource LightDirection}"
                                      Color="Black"
                                      Opacity="0.5" 
                                      BlurRadius="4" />
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>