1

I have a WPF CustomControl with a depdendency property called SelectedRange.

In an application in XAML the binding is set like this:

SelectedRange="{Binding Source={StaticResource ResourceKey=MainWindow},
                         Path=GlobalXRange, Mode=TwoWay}"

I find in the code that the BindingExpression is getting overwritten (set to null). I can determine this with this code:

public IRange SelectedRange
{
    get { return (IRange)GetValue(SelectedRangeProperty); }
    set
    {
        SetValue(SelectedRangeProperty, value);
        Binding b = BindingOperations.GetBinding(this, SelectedRangeProperty);

        BindingExpression be =
             BindingOperations.GetBindingExpression(this, SelectedRangeProperty);
        if (be == null)
        {
            Console.WriteLine("Binding expression is null!");
        }
    }
}

It turns out the BindingExpression is null after the application starts.

So my question is - how can I debug why this BindingExpression is null - e.g. it is set in XAML how can I find out where it is being set to null?

Note: There are no binding errors in the output console

9
  • Setter for SelectedRange will not be called if use binding. WPF will bind directly to your SelectedRangeProperty and call SetValue(...) directly on it Commented Nov 17, 2013 at 11:23
  • Ah that's true. I put the code in both SelectedRangePropertyChanged handler and the setter. It was called for both (it is being set via CLR setters and bindings). In all instances the binding expression is null (never appears to be set) Commented Nov 17, 2013 at 11:36
  • Is it always null? I've just created my simle UserControl with one DependancyProperty that is bound in MainWindow and when I check BindingExpression in PropertyChangedCallback it's never null Commented Nov 17, 2013 at 12:13
  • I think I've found it - I put a breakpoint in SelectedRangePropertChanged (DP callback) and I found that the SelectedRange is being set via a CLR setter before the binding is assigned. This means the binding cannot be assigned. Using DependencyObject.SetCurrentValue(SelectedRangeProperty, newValue) instead works. However ... I don't like this solution, it feels a bit too finely balanced. Also the code is cross-platform silverlight and there is no SetCurrentValue in SL Commented Nov 17, 2013 at 12:15
  • 1
    Now I know what you mean and I'm afraid that there is no obvious solution to your problem. I know the difference between SetValue and SetCurrentValue and, unfortunately, know all to well that SilverLight is constant workaround something that already exists in WPF Commented Nov 17, 2013 at 13:19

2 Answers 2

3

Ok guys, thanks to all your help I managed to solve this. For future readers here's how I did it.

This problem was caused by DependencyProperty Precedence. The TwoWay binding to SelectedRange was inside an ItemTemplate and was being overwritten by the Custom Control which was calling SetValue(SelectedRangeProperty, value).

The solution in WPF is to use SetCurrentValue(SelectedRangeProperty, value).

However, I am writing a cross-platform control (Silverlight, WinRT) and this method is not available in SL/WinRT. To workaround I had to create a binding to set the SelectedRangeProperty via a proxy in code, e.g.

var binding = new Binding();
binding.Source = this;
binding.Path = new PropertyPath(SelectedRangeProxyProperty);
binding.Mode = BindingMode.TwoWay;
this.SetBinding(SelectedRangeProperty, binding);

Thank you for all your help, hope this helps someone else!

Sign up to request clarification or add additional context in comments.

1 Comment

SetCurrentValue is the way to update control's DP indeed despite many suggestions to set two-way binding via FrameworkPropertyMetaData and then procceed with SetValue
2

You can enable tracing of the binding by adding the following to the binding expression:

PresentationTraceSources.TraceLevel=High

E.g.

{Binding
  Source={StaticResource ResourceKey=MainWindow},
  Path=GlobalXRange,
  Mode=TwoWay,
  PresentationTraceSources.TraceLevel=High}

You will then get additional information about the binding in the debug window.

1 Comment

That's useful. Im seeing generally the same result in the output window when the binding is updated. In the one case (using SetCurrentValue), then binding appears to be updated one way only. In the other case (SetValue) it is not updated back to the source. There are no outputs in the console window in this case as the binding expression for the property is null

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.