简体   繁体   中英

Style with Attached Properties Works In Root NameSpace, Fails in Nested Namespace or when accessed by external assembly

In compliance with the Minimal, Complete, and Verifiable Example Requirements:

The following resource dictionary:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:MCVE">
    <RadialGradientBrush x:Key="Glow">
        <RadialGradientBrush.RelativeTransform>
            <TranslateTransform X="0.0" Y="0.5" />
        </RadialGradientBrush.RelativeTransform>
        <GradientStop Color="#B28DD8FF" Offset="0.0" />
        <GradientStop Color="#008DD8FF" Offset="1.0" />
    </RadialGradientBrush>
    <Style x:Key="GlassButton" TargetType="{x:Type Button}">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="l:GlassButton.Glow" Value="{StaticResource Glow}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border
                        Background="{Binding
                            Background,
                            RelativeSource={RelativeSource
                                TemplatedParent}}"
                        BorderBrush="{Binding
                            BorderBrush,
                             RelativeSource={RelativeSource 
                                TemplatedParent}}"
                        BorderThickness="{Binding
                            BorderThickness,
                            RelativeSource={RelativeSource 
                                TemplatedParent}}"
                        CornerRadius="10">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <Border
                                x:Name="brdGlow"
                                Background="{Binding
                                            (l:GlassButton.Glow),
                                            RelativeSource={RelativeSource
                                                TemplatedParent}}"
                                Opacity="0" BorderThickness="1" Grid.RowSpan="2"
                                VerticalAlignment="Stretch" CornerRadius="4"/>
                            <ContentPresenter Grid.RowSpan="2"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation
                                        Duration="0:0:0.3" FillBehavior="HoldEnd"
                                        From="0.0"
                                        Storyboard.TargetProperty="(UIElement.Opacity)"
                                        Storyboard.TargetName="brdGlow" To="1" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation
                                        Duration="0:0:0.3" FillBehavior="Stop" From="1"
                                        Storyboard.TargetProperty="(UIElement.Opacity)"
                                        Storyboard.TargetName="brdGlow" To="0.0" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Reference in the App.xaml:

<Application
    x:Class="MCVE.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MCVE"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="MCVEStyle/GlassButton.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Within the Main Window:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:l="clr-namespace:MCVE"
    xmlns:lib="clr-namespace:System;assembly=mscorlib"
    x:Class="MCVE.MainWindow"
    mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
    <Button Style="{StaticResource GlassButton}"/>
</Window>

And defining the attached property:

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace MCVE {
    public class GlassButton {
        public static readonly DependencyProperty GlowProperty;
        static GlassButton( ) {
            GlowProperty = DependencyProperty.RegisterAttached(
                "Glow", typeof( Brush ), typeof( GlassButton ) );
        }

        public static Brush GetGlow( Button source ) =>
            source.GetValue( GlowProperty ) as Brush;
        public static void SetGlow( Button target, Brush value ) =>
            target.SetValue( GlowProperty, value );
    }
}

This code works. If you run the application, you will notice that, when you hover the cursor over the window, the glow fades in, and then the glow fades out when the mouse is no longer over the window.

This is fine.

However, when I nest the class name space, and reflect that change in the ResourceDictionary by changing l from MCVE to MCVE.NewNameSpace , and run the program, I get this error in the debug window:

System.Windows.Data Error: 40 : BindingExpression path error: '(l:GlassButton.Glow)' property not found on 'object' ''Button' (Name='')'. BindingExpression:Path=(l:GlassButton.Glow); DataItem='Button' (Name=''); target element is 'Border' (Name=''); target property is 'Background' (type 'Brush')

Why is this happening?

EDIT:

This is also happening when I attempt to reference this style and attached properties by another assembly, whether or not the class namespace is nested.

I could not get it running with your code - I am always getting this binding error : )

Please change your Binding to:

Background="{TemplateBinding l:GlassButton.Glow}"

or specify Path attribute:

Background="{Binding Path=(l:GlassButton.Glow), RelativeSource={RelativeSource TemplatedParent}}"

The explicite specification of Path is necessary as it seems that the parsing of the Binding is getting confused by the additional brackets {}. At least some other also had the same problem as you can see here .

in complete:

 <Border
       x:Name="brdGlow"
       Background="{TemplateBinding l:GlassButton.Glow}"
       Opacity="0" BorderThickness="1" Grid.RowSpan="2"
       VerticalAlignment="Stretch" CornerRadius="4"/>

Using this, I could move the namespaces around as I want and additionally specifying the attached property from xaml.

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