Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attached property to update style trigger on event

Tags:

c#

wpf

I'm trying to use an attached property to trigger a style change on a UIElement when an event has fired.

Here is the case scenario:

A user sees a TextBox, and focuses then unfocuses it. Somewhere in an attached property it notices this LostFocus event and sets a property (somewhere?) to say that it HadFocus.

The style on the TextBox then knows that it should style itself differently based on this HadFocus property.

Here's how I imagine the markup to look...

<TextBox Behaviors:UIElementBehaviors.ObserveFocus="True">
<TextBox.Style>
    <Style TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Behaviors:UIElementBehaviors.HadFocus" Value="True">
                <Setter Property="Background" Value="Pink"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</TextBox.Style>

I've tried a few combinations of the attached properties to get this working, my latest attempt throws a XamlParseException stating "Property can not be null on Trigger."

    public class UIElementBehaviors
{
    public static readonly DependencyProperty ObserveFocusProperty =
        DependencyProperty.RegisterAttached("ObserveFocus",
                                            typeof (bool),
                                            typeof (UIElementBehaviors),
                                            new UIPropertyMetadata(false, OnObserveFocusChanged));
    public static bool GetObserveFocus(DependencyObject obj)
    {
        return (bool) obj.GetValue(ObserveFocusProperty);
    }
    public static void SetObserveFocus(DependencyObject obj, bool value)
    {
        obj.SetValue(ObserveFocusProperty, value);
    }

    private static void OnObserveFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var element = d as UIElement;
        if (element == null) return;

        element.LostFocus += OnElementLostFocus;
    }
    static void OnElementLostFocus(object sender, RoutedEventArgs e)
    {
        var element = sender as UIElement;
        if (element == null) return;

        SetHadFocus(sender as DependencyObject, true);

        element.LostFocus -= OnElementLostFocus;
    }

    private static readonly DependencyPropertyKey HadFocusPropertyKey =
        DependencyProperty.RegisterAttachedReadOnly("HadFocusKey",
                                                    typeof(bool),
                                                    typeof(UIElementBehaviors),
                                                    new FrameworkPropertyMetadata(false));

    public static readonly DependencyProperty HadFocusProperty = HadFocusPropertyKey.DependencyProperty;
    public static bool GetHadFocus(DependencyObject obj)
    {
        return (bool)obj.GetValue(HadFocusProperty);
    }

    private static void SetHadFocus(DependencyObject obj, bool value)
    {
        obj.SetValue(HadFocusPropertyKey, value);
    }
}

Anyone able to direct me?

like image 709
mortware Avatar asked May 22 '12 13:05

mortware


1 Answers

Registering a readonly dependency property does not mean to add Key to the property name. Just replace

DependencyProperty.RegisterAttachedReadOnly("HadFocusKey", ...);

by

DependencyProperty.RegisterAttachedReadOnly("HadFocus", ...);

since HadFocus is the name of the property.

like image 61
Clemens Avatar answered Sep 20 '22 17:09

Clemens