Ramblings of a .NET Developer
Showing posts with label AttachedProperties. Show all posts
Showing posts with label AttachedProperties. Show all posts

15 December 2013

Sunday, December 15, 2013 | by Paul | Categories: , , | No comments
I've worked with WPF since it was in beta, and although it's super flexible with what you can do, sometimes I just want to cut down on the repetitive xaml I have to write.

How many times have you bound the visibility of a control to some viewmodel property or even to the boolean property of another element?
Well, I've done this literally hundreds of times and realized the other day that I can make it easy with a simple Attached Property.
So, below is a drop-in helper class to make your binding easier without having to use a converter. Oh, use VisibilityHelper.Inverse="True" if you want the opposite result.

public class VisibilityHelper
    {

        public static bool GetIsVisible(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsVisibleProperty);
        }

        public static void SetIsVisible(DependencyObject obj, bool value)
        {
            obj.SetValue(IsVisibleProperty, value);
        }

        // Using a DependencyProperty as the backing store for IsVisible.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsVisibleProperty =
            DependencyProperty.RegisterAttached("IsVisible", typeof(bool), typeof(VisibilityHelper), new UIPropertyMetadata(true, OnIsVisibleChanged));

        public static bool GetInverse(DependencyObject obj)
        {
            return (bool)obj.GetValue(InverseProperty);
        }

        public static void SetInverse(DependencyObject obj, bool value)
        {
            obj.SetValue(InverseProperty, value);
        }

        // Using a DependencyProperty as the backing store for Inverse.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty InverseProperty =
            DependencyProperty.RegisterAttached("Inverse", typeof(bool), typeof(VisibilityHelper), new UIPropertyMetadata(false, OnIsVisibleChanged));

        private static void OnIsVisibleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            UpdateVisibility(sender as UIElement);
        }

        private static void UpdateVisibility(UIElement fe)
        {
            if (fe != null)
            {
                bool value = (bool)fe.GetValue(VisibilityHelper.IsVisibleProperty);
                if ((bool)fe.GetValue(VisibilityHelper.InverseProperty))
                {
                    fe.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
                }
                else
                {
                    fe.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
                }
            }

        }
    }

Now, add this to your favorite UI library and away you go!
As an example, the button below is hidden if it is disabled.

14 December 2013

Saturday, December 14, 2013 | by Paul | Categories: , , | No comments
So the projects I work on are usually quite large, often hitting over 1m lines of code. And, sometimes it is nice to add some buttons into the application which are there just for development purposes.

As one of my developers was hacking a way of doing this by leaving this out of his commits, it seemed like an opportunity to add something to reduce this management effort and eliminate errors when committing and pushing code in mecurial.

So, below is a simple attached property that will only render the control when the app is a DEBUG build.

    public static class Runtime
    {
        public static bool GetDebugOnly(DependencyObject obj)
        {
            return (bool)obj.GetValue(DebugOnlyProperty);
        }

        public static void SetDebugOnly(DependencyObject obj, bool value)
        {
            obj.SetValue(DebugOnlyProperty, value);
        }

        // Using a DependencyProperty as the backing store for DebugOnly.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DebugOnlyProperty =
            DependencyProperty.RegisterAttached("DebugOnly", typeof(bool), typeof(Runtime), new UIPropertyMetadata(false, OnDebugOnlyChanged));

        private static void OnDebugOnlyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var ui = sender as UIElement;
            if (ui != null)
            {
                if ((bool)e.NewValue)
                {
#if !DEBUG
                ui.Visibility = Visibility.Collapsed;
                ui.IsEnabled = false;
#endif
                }
            }
        }
    }

Now just just use the attached property where you need to.