0
votes

In WPF, if I want to reference the whole object (not a specific property) in a binding, I can write any of the following:

  • {Binding Path=.}
  • {Binding .}
  • {Binding}

Like so:

<ItemsControl ItemsSource="{Binding Widgets}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <controls:WidgetControl Widget="{Binding}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

However in WinRT I have not been able to get this to work:

<GridView ItemsSource="{Binding Source={StaticResource Widgets}}">
    <GridView.ItemTemplate>
        <DataTemplate>
            <controls:WidgetControl Widget="{Binding}"/>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

It fails with a very vague exception:

The text associated with this error code could not be found.
Failed to assign to property 'XX.WidgetControl.Widget'. [Line: XX Position: XX]

The ItemsSource binding works because the DataContext of each controls:WidgetControl gets set to a Widget. And I know the obvious answer to this is just to wait for the DataContext to be set and cast that to a Widget inside my widget control. But I'm asking on principle: Why doesn't self-binding work in WinRT... or is there a notation to make it work?

1
Self-binding works in WinRT as you've tried: Widget="{Binding}". What type is Widget? - Dani
I don't understand the question: Widget is of type Widget. It's a custom class I created for the purposes of this question. It can be any class. I'm glad it works for you, however I'm getting the exception referenced in the question. Do you have any idea why? - josh2112
No sorry, usually it works in that way. Just to be sure, do you really work with this code: ItemsSource="{Binding Source={StaticResource Widgets}}"? Because I'm not sure whether your ItemsSource can be bind to StaticResource. - Dani
Sure you can. It's how the default Grid App Sample in Visual Studio 2013 does it. The collection is in the view model, but the Page's resources section defines a CollectionViewSource wrapping the collection, and that's what the GridView binds to. It's for grouping/sorting/filtering/etc. of the GridView. It looks like this: <CollectionViewSource x:Name="Widgets" Source="{Binding Widgets}"/>. - josh2112
Just asking if you managed to solver your problem josh2112? If so, what was the issue? - Gavin Lanata

1 Answers

0
votes

So it turns out {Binding} works just great. I had wrongly set the DataContext in my WidgetControl, causing the binding to fail and leading me to believe the WinRT binding mechanism was at fault.

To be clear, {Binding .} still doesn't work like it does in WPF as best as I can tell. It interprets the dot as a literal property name instead of a reference to self:

Error: BindingExpression path error: '.' property not found on 'Widget'. BindingExpression: Path='.' DataItem='Widget'

But my actual problem was trying to change the DataContext at the root level of my WidgetControl, causing any external bindings to fail. Because I defined my control as <UserControl x:Name='controlRoot' DataContext="{Binding ElementName=controlRoot}, the binding in <controls:WidgetControl Widget="{Binding}"/> was referencing the WidgetControl itself and not the Widget I was trying to pass in. And the "failed to assign to property" exception was thrown by a property changed handler that was expecting a Widget, not a WidgetControl.

So you can absolutely use {Binding} to reference the DataContext of the thing the binding is on, just don't try to set the path to ".".