Tim Hibbard

CEO for EnGraph software
posts - 629 , comments - 1660 , trackbacks - 459

My Links

News



Add to Google

Twitter












Tag Cloud

Article Categories

Archives

Post Categories

Image Galleries

EnGraph Blogs

Links

Other

Roll

WPF Custom Control Dependency Property Gotcha

Let's say you have a custom WPF control called SearchTextBox.  It has a textbox and a button labeled "search".  Simple enough, you reuse it in your application when you want to provide search. 

Then one day, you decide you need this control needs to be bindable.  So you expose a public property Text and map it to textSearch just like you would in WinForms.

Well, that doesn't work, so you google around and stumble upon Dependency Properties and learn how to create your own (VS snippet shortcut propdb) and create a Text DP.

Now you spend 30 minutes trying to map your Text DP to your textSearch.Text until you finally figure out that your DP snippet lead you astray and there is one more step that didn't get included in the shortcut.  In the UIPropertyMetaData, you need to specify a function to call when the property changes - so you can set textSearch.Text.

The function looks like this:

static void textChangedCallBack(DependencyObject property, DependencyPropertyChangedEventArgs args) { SearchTextBox searchTextBox = (SearchTextBox)property; searchTextBox.textSearch.Text= (string)args.NewValue; }

And the rest of the DP looks like this:

public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof(string), typeof(SearchTextBox), new UIPropertyMetadata(string.Empty, new PropertyChangedCallback(textChangedCallBack)));

 

The important part here is what wasn't created by the VS snippet :

new UIPropertyMetadata(string.Empty, new PropertyChangedCallback(textChangedCallBack))

Now you are binding to your custom control and all is good.

 

Print | posted on Tuesday, April 22, 2008 1:11 AM | Filed Under [ .NET WPF ]

Feedback

Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Umm, why should you need to do this? The binding should work perfectly well without it.
5/15/2008 12:38 PM | Dmitri
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Actually, it doesn't. I've tried :)
5/15/2008 12:42 PM | Tim Hibbard
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

My example was for people that needed to bind their business objects to a user control, which requires a DP...unless I'm wrong.
5/15/2008 3:42 PM | Tim Hibbard
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Mike's thing works well. The thing I missed was adding a X:Name to the <Window.
5/20/2008 1:24 PM | Nick
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Thanks very much Tim. Took me forever to figure out how to do this!

If want to re-use the callback function you can fetch the argument name like so:

if (args.Property.Name.Equals("Text"))
{
searchTextBox.textSearch.Text= (string)args.NewValue;
}

7/29/2008 12:38 AM | Lach
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Thank you Tim!

I spent most of yesterday trying to solve this problem, and looking at your solution it makes sense.. just wish I found your post a bit earlier :-)
3/17/2009 5:17 AM | Chris
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

You can't access the property in the constructor. You need to get it in the UserControl_Loaded event.
3/20/2009 2:58 AM | Alex Kwiatkowski
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

I've tried all those methods, they work well my Main problem is that its OneWay binding .(ie the textbox in UserControl changes its text when the property in my class changes, but typing in the text box dosen't change the underlaying property.)
This is my 11th day on this, pls i really need help. Thanx alot.
9/9/2009 5:47 AM | Majeed
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

wow ... wish i would have found this post yesterday ! i have been abusing google for this for some time. i got mike's sugestion to work for me ... thanks guys. loads of infomation.
11/3/2009 10:47 AM | John Little
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Thanks for posting this. Wish I would have found it sooner. It's surprising that something like this is more clearly spelled out in the MSDN docs.
12/10/2009 12:22 PM | Jake
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Hi

I have a problem that drives me crazy: I have a usercontrol (UcSelect=textbox+button) which works as expected when used as a "single control" when used this way:
<local:UcSelect Grid.Row="1" x:Name="ucSingle1" UcText="{Binding FirstName, Mode=TwoWay}"/>
When I use it in a datagridcolumn all is fine but the changes I make in the column are not going back in my "FirstName" property.
I think the problem is my "GenerateEditingElement", maybe someone can help me out?
Here is the derived column:
Public Class DerivedColumn
Inherits DataGridTextColumn

Protected Overloads Overrides Function GenerateElement(ByVal oCell As DataGridCell, ByVal oDataItem As Object) As FrameworkElement

Dim oElement = MyBase.GenerateElement(oCell, oDataItem)
Return oElement

End Function

Protected Overloads Overrides Function GenerateEditingElement(ByVal oCell As DataGridCell, ByVal oDataItem As Object) As FrameworkElement

Dim oUc As New UcSelect
Dim oBinding As Binding = CType(Me.Binding, Binding)
oUc.SetBinding(UcSelect.UcTextProperty, oBinding)
Return oUc

End Function

End Class

And here is the Codebehind of my usercontrol:
Private Shared Sub textChangedCallBack(ByVal [property] As DependencyObject, ByVal args As DependencyPropertyChangedEventArgs)
Dim UcSelectBox As UcSelect = DirectCast([property], UcSelect)
UcSelectBox.SetValue(UcTextProperty, args.NewValue)
End Sub

Public Property UcText() As String
Get
Return GetValue(UcTextProperty)
End Get

Set(ByVal value As String)
SetValue(UcTextProperty, value)
End Set
End Property

Public Shared ReadOnly UcTextProperty As DependencyProperty = _
DependencyProperty.Register("UcText", _
GetType(String), GetType(UcSelect), _
New FrameworkPropertyMetadata(String.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, New PropertyChangedCallback(AddressOf textChangedCallBack)))

Public Sub New()

' This call is required by the Windows Form Designer.
InitializeComponent()
grid1.DataContext = Me

End Sub

3/19/2010 3:48 PM | Klaus Wiesel
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

This works binding from a parent window to user control, but you cant set the dependecny property in the user control and have that value in the parent window. In fact, if the depenecy value in the user control is set to exactly what is saved in the parents bound dependy then the propertyChangedCallBack wont fire at all... this is especially troubling for bools and giving me a headache
7/22/2010 11:25 PM | Cyrel
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

In fact, DP stands for "double penetration" and there are other abbreviations like DPP and DAP that its not worth to explain here.
At same time it's not WPF, it is WTF (Windows Troublemaker Foundation). The next step in app development!!

Anyways, your post was useful for me, I was fighting against that bindable properties on my UserControl and your post was very nice.
9/1/2010 3:41 AM | Commentor
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Use the following line of code in SearchTextBox's constructor, then you won't have to use the PropertyChangedCallback.

textSearch.SetBinding(TextProperty, "Text");
9/28/2010 3:35 AM | Jannes
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Ignore previous comment.
The SetBinding method does nothing, you must use PropertyChangedCallback.
9/28/2010 7:08 AM | Jannes
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

yes you should probably use PropertyChangedCallback
1/5/2011 11:57 PM | electronic medical records
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Hey,

you missunderstood the using of the changed-call-back. Try following in your Control:

1. Make a DP with Name "Text" like in first post.
2. Name your userControl with x:Name="MyUserControl"
3. Bind you new Text-Property in your xaml:

<TextBox Text={Binding Path=Text, ElementName=MyUserControl, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"} />

The mode TwoWay garants the refresh in both directions and the UpdateSourceTrigger=PropertyChanged sets the event when the property will be refreshed(the default is set to LostFocus)

In the ChangedCallback you can call you own events, i.E. if you need a event for TextChanged make one and invoke this in the callback.
1/12/2011 7:51 AM | Khar
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

I think they should call this post.

The bringer of Silverlight developers back from the brink of insanity.

nuf said
1/14/2011 7:34 PM | Nigel Stratton
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Thanks to Khar!
it took me many days how to bind to my dp by XAML, and I was expecting that using the change-call-back should not be the solution.

This was the key I was missing:

2. Name your userControl with x:Name="MyUserControl"

After that I could bind to my dp.
Thanx a lot!

1/28/2011 4:21 PM | R.LUEBESS
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

There is another way without proppertyChangedCallback.

Even this is probably very easy once you know it, but this "simple" issue also took me several days to find out how exactly it works. So I would like to share another way without proppertyChangedCallback-methode:

1. Make a DP with Name "Text" like in first post (without the textChangedCallBack.)
2. set a DataContext in your UserControll DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"

<UserControl x:Class="SearchTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
...
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
...
>


3. Bind you new Text-Property in your xaml:
<TextBox Text={Binding Path=Text, Mode=TwoWay, updateSourceTrigger=PropertyChanged"} />

Make sure to set the DataContext within the UserControl directly, not within another control later. Because you want "Self" to ref to the UserControl.

Maybe this simple thing can help some beginners to get to the next level... (and avoid from missunderstanding the PorpertyChangedCallback)

BR,
Rolf
2/1/2011 4:11 AM | R.LUEBESS
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Hi i am very new to WPF. Tried your example, my textChangedCallBack wouldn't fire, I had to add textchanged event on textSearch in usercontrol, and in it Setvalue to dp Textproperty, then it worked.

Am I missing something:(
2/9/2011 3:12 PM | Vk123
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Thanks very much ; I've been beating my head over getting a DP to work properly in a usercontrol until I saw your tip. Works great!
3/21/2011 1:07 PM | An Nonny Mouse
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Thank you, life saver!
3/31/2011 4:56 PM | Andrei
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Thank you very much
4/26/2011 2:15 PM | free gift cards
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

Thanks never thought there would be an easier way to get things like this done.
7/5/2011 10:19 AM | medical transcription services
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

THANKS !!!
1/19/2012 12:47 PM | sergey
Gravatar

# re: WPF Custom Control Dependency Property Gotcha

I love you man.
1/19/2012 5:41 PM | Sam
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 
 

Powered by: