简体   繁体   中英

Why is my Dependency Property written with the propdp snippet not working?

I have a class with a simple dependency property that I wrote with the help of the propdp snippet in Visual Studio. I derived the class from TextBox and gave it a PrePend property that I want to be a dependency property. I want it so that if the user sets PrePend to "Hello " and Text to "World", the Text getter will return "Hello World". My problem is that the code is seemingly ignoring my PrePend dependency property.

My class is here:

internal class MyTextBox : TextBox
{
    public new string Text
    {
        get { return this.PrePend + base.Text; }
        set { base.Text = value; }
    }

    public string PrePend
    {
        get { return (string)GetValue(PrePendProperty); }
        set { SetValue(PrePendProperty, value); }
    }

    // Using a DependencyProperty as the backing store for PrePend.  
    //   This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PrePendProperty =
        DependencyProperty.Register("PrePend", typeof(string), 
          typeof(MyTextBox), new PropertyMetadata(""));
}

I got this code by using the propdp snippet. I only added the Text setter.

My XAML code is simply this:

<local:MyTextBox PrePend="Hello " Text="World" />

When I run the code, the screen displays "World". I put breakpoints in the Text getter and setter, and the PrePend getter and setter, but the code never breaks there.

What am I doing wrong with this simple example? Should I not use the propdp code snippet to do this? I don't understand dependency properties very well.

This is "illegal" as WPF always access the DependencyProperties directly, the property is nothing more than a wrapper. That's why you should never change or put logics in the properties, they will never be used by wpf internally!

public new string Text // Bad pie!
{
    get { return this.PrePend + base.Text; } // Bad pie!
    set { base.Text = value; }
}

If you want to do something when a property changes add a OnPrePendPropertyChanged handler when declaring your dependency property.

IE:

public static readonly DependencyProperty PrePendProperty = DependencyProperty.Register("PrePend", typeof(string), typeof(MyTextBox), new PropertyMetadata(String.Empty, OnPrePendPropertyChanged ));

private static void OnPrePendPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
   var ctl = sender as MyTextBox ;
   ctl.OnPrePendChanged();
}

protected virtual void OnPrePendChanged()
{
   // do your magic here
}

You can also add handlers to existing dependency properties, like your text property there. This must be done in the static constructor of the class. This is described in this post .

static MyTextBox 
{
    DefaultStyleKeyProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(typeof(MyTextBox)));
    TextBox.TextProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnTextPropertyChanged)));
}

// Add your handlers as above

Personally when possible, I would rather create a Behavior for just IE extending functionality of controls.

In this current situation( I suspect you are experimenting? ), I would consider using a std TextBox and then just bind to the Text property to a prop on the vm and do your magic there, and/or use a IValueConverter in the binding.

Hope it helps

Cheers,

Stian

The setter is not used by WPF when changing the value due to databinding/animation updates.

If you want to respond to changes in a dependency property you can do one of two things:

  1. Add a PropertyChanged handler to the PropertyMetaData in the register call.

  2. Do not handle the change in the control, instead handle it in the ViewModel.

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