Bind button click back to object when using BindableCollection

Aug 11, 2013 at 2:00 AM
I am using an ItemsControl and binding it to a BindableCollection<CustomObject>. A button is shown for each item. I can display the appropriate text on the button easy enough by binding to a property on the CustomObject, but I can't seem to figure out how to bind the click event back to a function on the object each button represents.

I tried adding Click="{Binding run}", but then I get an InvalidCastException: "Unable to cast object of type 'System.Reflection.RuntimeEventInfo' to type 'System.Reflection.MethodInfo'." I've been searching on Google for tips for a while and finally gave up and decided to ask you guys. :)

XAML below for what its worth. My run() function on the object is just a standard public void function.
                <ItemsControl ItemsSource="{Binding Collection}" >
                    <ItemsControl.ItemTemplate>
                        <ItemContainerTemplate>
                            <Button Content="{Binding First}"/>
                        </ItemContainerTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
Aug 11, 2013 at 4:12 AM
Edited Aug 11, 2013 at 4:14 AM
recursiverror wrote:
I am using an ItemsControl and binding it to a BindableCollection<CustomObject>. A button is shown for each item. I can display the appropriate text on the button easy enough by binding to a property on the CustomObject, but I can't seem to figure out how to bind the click event back to a function on the object each button represents.

I tried adding Click="{Binding run}", but then I get an InvalidCastException: "Unable to cast object of type 'System.Reflection.RuntimeEventInfo' to type 'System.Reflection.MethodInfo'." I've been searching on Google for tips for a while and finally gave up and decided to ask you guys. :)

XAML below for what its worth. My run() function on the object is just a standard public void function.
                <ItemsControl ItemsSource="{Binding Collection}" >
                    <ItemsControl.ItemTemplate>
                        <ItemContainerTemplate>
                            <Button Content="{Binding First}"/>
                        </ItemContainerTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
<Button Content="{Binding First}" cm:Message.Attach="[Event Click] = [Action Run($eventArgs)]" />

something like that where cm = Caliburn.Micro reference in your xaml, I am assuming you wanted to pass the click event but you could pass $datacontext to pass the object associated location in the collection that was clicked.

Edit - Reread your situation I don't know that you will be able to call a method with in the object in question, it would need to be in the viewmodel that populated the view.

Hope this helps...

Morgan.
Aug 11, 2013 at 1:27 PM
Using what you have listed with $eventArgs, it does indeed call into my object when the button is clicked.

I was thinking about what I wanted to do a little more, and I think I really want to call one function on the ViewModel and pass it the object. I tried an experiment by adding a function to my VM, changing the XAML for the name of the function and to use the $dataContext, and it called into my VM with the corresponding object from the Button. Pretty cool!

Then just for fun, I named the function the same in both the VM and the object, and it called the function in the VM. Removing the function from the VM then makes it call into the object. I'm sure CM must be looking at the hierarchy and trying to find the first matching function. I'll eventually figure all this out and understand the finer details! :)

Thanks Caliburn.Micro for making my life easier and thanks Morgan for pointing me in the right direction.

Sean
Aug 12, 2013 at 4:35 AM
glad that it is working for you :)