Using DataTemplates in a CollectionView... I can call a ViewModel's Command from a button like this:
<Button Text="Test"
Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}},
Path=BindingContext.TestCommand}"/>
Or from a gesture like this:
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}, Path=BindingContext.TestCommand}"/>
</Frame.GestureRecognizers>
So, why can't I call that command from an Entry's TextChanged Event like this?
<Entry x:Name="PortionEntry"
Text ="{Binding QtyTest, Mode=TwoWay}">
<Entry.Behaviors>
<behavors:EventToCommandBehavior
EventName="TextChanged"
Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}},
Path=BindingContext.TestCommand}"/>
</Entry.Behaviors>
The code for EventToCommandBehavior works when not used in a DataTemplate
Here is a project illustrating the issue: https://github.com/BullCityCabinets/DataTemplateEventIssue
I got the button code form these fine folks: https://www.syncfusion.com/kb/11029/how-to-bind-command-from-viewmodel-to-external-itemtemplate-of-xamarin-forms-listview
Thanks!
I've looked at your example code and you appear to be using the Xamarin Forms Example code to implement your
EventToCommandBehavior. This is also implemented in the Xamarin Community Toolkit in roughly the same manner. Note that these implementations inherit fromXamarin.Forms.Behavior.I also tried these examples to perform a Relative Source binding in a
DataTemplateassigned to anItemsViewbut when I would run the example (same as yours above) I would receive anInvalidOperationExceptionat:Heading over to the Xamarin source code you can see that the throw is a result of the binding
targetObjectnot inheriting fromXamarin.Forms.Elementwhen applying the binding inBinding.ApplyRelativeSourceBinding(). SinceEventToCommandBehaviorinherits fromXamarin.Forms.Behaviorthis is the result.The Xamarin Relative Binding docs don't specifically mention that the Binding Target requirement, they concern themselves with the binding Source obviously. But they do mention that these bindings search the Visual Tree or are relative to the Element:
Since a
Behaviorisn't anElementand isn't part of the Visual Tree (It's stored in theVisualElement.Behaviorsproperty), the binding doesn't have direct access to either to perform it's "search" during runtime and thus the binding can't ever be satisfied.I solved this by extending Entry and adding commands where needed. It's not the most reusable solution since I have to do it on other Elements like Switch but it works.
And the xaml embedded inside a
DataTemplate:Update: After a few days of experimentation I've found another possible pattern to support this in a more generic fashion. I'll leave it up to the reader to decide on it's merits. I'm currently inclined to think it's a reasonable paradigm and is generic so there's no need to extend a bunch of existing Visual Elements.
The code presented below models the idea of an Observer that holds the command and observes an event of it's child. The parent/observer extends the bland
Xamarin.Forms.ContentViewelement with the Command/CommandParameter/Converter that we see implemented in the Xamarin Forms Example code and combines that with an Attached Property implementation for the EventName.The
ContentView.Contentproperty holds a singleXamarin.Forms.Viewobject so there's no confusion with respect to the target of the Attached property. Event Handlers are all static so there shouldn't be any leaking issues.And this alternate xaml embedded inside a
DataTemplate: