WPF Binding problems when not setting DataContext
I have successfully created a number of UserControls with various functionality setting the DataContext on each control to 'this'. I've always had problems when trying to split them into smaller 'inner' UserControls that will be more useable. The problem is this:
When the DataContext is set to 'this', I can bind to Properties in the code behind - they don't have to be DependencyProperties. When binding to ordinary properties, the program execution enters the code behind, where I can do things like switch ListBox items or other things that I can't do in xaml.
But when I create a new 'inner' UserControl that is hosted in the original control and move these properties to the inner control, I now have to upgrade them to be DependencyProperties, so that I can bind to them from the original control. When binding to DependencyProperties, the program execution never enters the code behind and for me, THIS is the problem. By the way, I dont set the DataContext in the inner control but instead set the Name property of the root element and use the ElementName=UserControlName syntax in the binding of inner control properties.
I am aware that I can add a ValidateValueCallbackHandler to a DependencyProperty to gain access to the code behind as the bound value changes, but it must be a static method, so I can't access any non static members (ie. my whole class).
One example is that I have a DurationPicker control that displays TimeSegments objects in ListBoxes. A TimeSegments objects is basically an ObservableCollection of TimeSegment objects and a TimeSegment has StartDate, EndDate and Duration properties. I have a MinutesPerSegment property in the DurationPicker control that was bound to values from a ComboBox. It worked perfectly. I could change the ComboBox value and the code behind would put the correct number of TimeSegment objects with the correct new values in the ListBox.
Then I created the inner control that contains a TimeSegments object and a ListBox to display it. Now the MinutesPerSegment property had to become a DependencyProperty so that I can bind to it from the outer control and program execution never enters the code behind, so now I can't alter the number of TimeSegmentobjects in the collection.
One other thing to note. I can successfully bind to the DependencyProperties of the inner control from the outer control - I can see the changes showing in the UI. The problem is just that I need the program execution to enter the code behind when certain bound properties are updated.
What is the correct way to do this? Many thanks.
EDIT - In the example, if I create the TimeSegments objects in the outer control and bind these to the inner control then it still works. This is because the MinutesPerSegment property in the outer control is an ordinary property... However, I want each TimeSegments object to be dealt with in its own inner TimeSegmentsRow control... and so the problem.
First, you needn't set DataContext
to this
just to enable binding to properties of your custom control. That's a bad idea in case anyone decides to set another datacontext for your control. You can use relative binding instead.
{Binding Path=PathToProperty,
RelativeSource={RelativeSource AncestorType=
{x:Type namespaceAlias:typeOfYourControl}}}
and declare namespace alias for your custom control in xaml
xmlns:namespaceAlias="clr-namespace:YourLibraryNamespace;assembly=YourLibraryAssemblyName"
Second, wpf will not use your property getter and setter to access your dependency properties, that's why there should not be any additional logic beyond GetValue
and SetValue
. You can specify PropertyChangedCallback when registering your property to add some logic when property changes.
上一篇: 如何绑定WPF中两个数据绑定值的总和?