Add dependency property to control

user31673 picture user31673 · May 3, 2009 · Viewed 18.6k times · Source

I am using the Infragistics XamDateTimeEditor control and I want to add a dependency property to it to allow the developer to choose to have all the text selected when the control gets focus. I have created a style that is used to set the behavior I want but I want the developer to decide if the behavior should be executed based on a boolean dependency property. I am not sure how that is done.

Answer

Denis Troller picture Denis Troller · May 3, 2009

I assume you inherited from XamDateTimeEditor for this.

If you can write the code referencing a "standard" (clr) property, then you are good to go:

  1. declare your DependencyProperty
  2. remove your backing field and replace the implementation of the standard property so that it accesses the DependencyProperty instead of the backing field.

    public class MyXamDateTimeEditor : XamDateTimeEditor
    {
        public static readonly DependencyProperty IsSelectOnFocusEnabledProperty = 
          DependencyProperty.Register("IsSelectOnFocusEnabled", typeof(bool), 
        typeof(MyXamDateTimeEditor), new UIPropertyMetadata(false));
    
        public boolIsSelectOnFocusEnabled
        {
            get
            {
                return (bool)GetValue(IsSelectOnFocusEnabledProperty);
            }
            set
            {
                SetValue(IsSelectOnFocusEnabledProperty, value);
            }
        }
    }
    

Then, when you access IsSelectOnFocusEnabled in your code it will return the current value of the Dependency Property.

You can also set it up to receive notification whenever the property changes, but I don't see why you would in your case.

There is also another option for this trick, which uses no inheritance and an attached property if you'd like.

UPDATE:

OK, since it was requested, here's a way to achieve that for any textbox. It should be easy to translate to whatever event you use to carry that out on another type of control.

    public class TextBoxBehaviors
    {
        public static bool GetIsSelectOnFocusEnabled(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsSelectOnFocusEnabledProperty);
        }

        public static void SetIsSelectOnFocusEnabled(DependencyObject obj, bool value)
        {
            obj.SetValue(IsSelectOnFocusEnabledProperty, value);
        }

        public static readonly DependencyProperty IsSelectOnFocusEnabledProperty =
            DependencyProperty.RegisterAttached("IsSelectOnFocusEnabled", typeof(bool), 
            typeof(TextBoxBehaviors), 
            new UIPropertyMetadata(false, new PropertyChangedCallback(OnSelectOnFocusChange)));

        private static void OnSelectOnFocusChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is TextBox)
            {
                var tb = d as TextBox;
                if ((bool)e.NewValue)
                {
                    tb.GotFocus += new RoutedEventHandler(tb_GotFocus);
                }
                else
                {
                    tb.GotFocus -= new RoutedEventHandler(tb_GotFocus);
                }
            }
        }

        static void tb_GotFocus(object sender, RoutedEventArgs e)
        {
            var tb = sender as TextBox;

            tb.SelectAll();
        }

    }

The way you use it is as follows, for example:

<Window x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication2"        
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TextBox Text="No Select All" x:Name="TextBox1"/>
        <CheckBox Content="Auto Select"
                  Grid.Column="1"
                  IsChecked="{Binding Path=(local:TextBoxBehaviors.IsSelectOnFocusEnabled), ElementName=TextBox1, Mode=TwoWay}" />
        <TextBox Grid.Row="1" Text="djkhfskhfkdssdkj"
                 local:TextBoxBehaviors.IsSelectOnFocusEnabled="true" />
    </Grid>
</Window>

This shows you how to set up the property to activate the behavior, and how to bind it to something else if need be. Note that this specific example is not perfect (if you tab through it works, if you click inside the control, the textbox has internal logic that actually deselects the text, but that's just an example on how to attach behaviors to controls through attached properties).