Search code examples
c#wpfdata-bindingdatatemplate

Binding within DataTemplate does not work on first load of view


I have a dependency property on a custom control that I am trying to bind to a property in the view model. The control is inside of a DataTemplate in the view (a UserControl). However, the binding seems to only function if the binding characteristics are changed after the view loads.

So, here's an example of what's in the view's XAML:

<dxb:BarStaticItem Alignment="Far">
    <dxb:BarStaticItem.ContentTemplate>
        <DataTemplate>
            <controls:AllMaxDateRangeCombo Grid.Row="1"
                                           DateRange="{Binding DataContext.WorkOrderDateRange, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=UserControl}}"
                                           TimeFrameType="Current"
                                           Width="150" />
        </DataTemplate>
    </dxb:BarStaticItem.ContentTemplate>
</dxb:BarStaticItem>

BarStaticItem is a DevExpress control used when putting "normal" controls in a toolbar. The binding that I have defined in the AllMaxDateRangeCombo does not function when the view is first loaded. But at runtime (during debug), if were to change the property name by adding a digit to the end of it, and then immediately removing that digit, the binding would then begin to work.

For lack of better understanding, I can only say that it seems like the binding is not being "hooked up" properly at first load, or that it tries before some piece of it is ready. But then when I make a change at runtime, suddenly it's linked.

I hope this makes sense enough for someone to help me work out what is going on here.

P.S.: using the Snoop tool, I can see that the control's dependency property DateRange has no binding on it at all until I make that runtime change. Then, a binding appears. So for whatever reason, the binding I have defined simply doesn't kick in at first load of the view.

EDIT: in response to a question I'll explain a bit of the mechanics. The AllMaxDateRangeCombo is basically a ComboBox with choices like LastMonth, Today, LastWeek, etc. When a selection is made, the date range is recalculated and assigned to the control's DateRange dependency property. Since that is the property I am trying to bind to, I expect the UI view model's property to change along with it. Then I would respond and update UI data. But that property value never changes. Hence, either the binding is never really getting hooked up, or it is somehow unable to notify changes.


Solution

  • This ended up being due to how the values in the control were being changed. In the control, this dependency property was defined:

    public static DependencyProperty DateRangeProperty = DependencyProperty.Register("DateRange", typeof(DateTimeRange), typeof(AllMaxDateRangeCombo), new PropertyMetadata(new DateTimeRange(DateTime.MinValue, DateTime.MaxValue)));
    public DateTimeRange DateRange
    {
        get => (DateTimeRange)GetValue(DateRangeProperty);
        set => SetValue(DateRangeProperty, value);
    }
    

    After the combo box selection changed, that value was being set:

    private void RecalculateDates()
    {
        DateRange = new DateTimeRange(DateTime.MinValue, DateTime.MaxValue);
    }
    

    That worked fine in a two-way binding so long as the usage of the control was not in a DataTemplate. But once it was used in a DataTemplate, then only this version works:

    SetCurrentValue(DateRangeProperty, new DateTimeRange(DateTime.MinValue, DateTime.MaxValue));