Search code examples
c#wpfmvvmdata-bindingicommand

Triggering External ICommands/Functions from inside a ListItem


I'm wondering what the best method is for triggering external functions (or commands) from within a inner list item.

For example, I have a FooManager object which contains an ObservableCollection of Foo objects called MyFoos. FooManager also has a function called ProcessFoo(Foo foo).

<StackPanel DataContext="FooManager">
   <ListView ItemsSource="{Binding MyFoos}" >
        <ListView.ItemTemplate>
            <DataTemplate>
                <WrapPanel>
                    <Button Content="Do Something"
                            Command="{Binding Path=SomeFooCommand} />
                </WrapPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackPanel>

How do I trigger the ProcessFoo(Foo foo) function (and passing the 'clicked' Foo) by clicking the "Do Something" button?

I realise I could use code-behind to do this, but I'm wondering what the cleanest MVVM approach is. Should the ViewModel for Foo contain a reference to it's FooManager, or is it bad practice for ViewModels to reference each other?


Solution

  • Thanks to @Clemens. In the FooManager class, add a command which takes a Foo VM as a parameter. The Button in the DataTemplate can then trigger this by using a RelativeSource in the binding, and passing itself (an empty {Binding}) as parameter.

    <StackPanel DataContext="FooManager">
       <ListView ItemsSource="{Binding MyFoos}" >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <WrapPanel>
                        <Button Content="Do Something"
                                Command="{Binding Path=DataContext.ProcessFoo, RelativeSource={RelativeSource AncenstorType=ListView}}
                                CommandParameter={Binding} />
                    </WrapPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackPanel>