I have a ListView in my MVVM WPF implementation, it has a DataTemplate with a button inside. The ListView is bound to a collection of complex objects in the ViewModel.
<ListView ItemsSource="{Binding Path=ComplexObjects}"
SelectedItem="{Binding Path=SelectedObject}"
Width="Auto">
<ListView.View>
<GridView>
<GridViewColumn Header="My Property">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Margin="6,2,6,2">
<TextBlock Text="{Binding MyProperty}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="First Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Margin="6,2,6,2">
<Button Command="{Binding ???}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
All the text fields are bound with no problem, but can I bind the Button Command to a member method of the ComplexObject? If so is there any way to pass parameters?
I have a feeling I'm probably just evading using an ICommand.
Thanks.
You could bind an ICommand
on the ViewModel, passing the instance to invoke the method on as a parameter. The ViewModel can then call the appropriate method on the right ComplexObject
.
For example:
<DataTemplate>
<StackPanel Margin="6,2,6,2">
<Button Command="{Binding DoSomethingCommand, RelativeSource={RelativeSource AncestorType={x:Type ViewModelType}, Mode=FindAncestor}" CommandParameter="{Binding}"/>
</StackPanel>
</DataTemplate>
Then the viewmodel could look like so:
public ICommand DoSomethingCommand
{
get { return new DelegateCommand<object>(DoSomething); }
}
private void DoSomething(object instance)
{
var complexObject = instance as ComplexObject;
if (complexObject != null)
complexObject.SomeMethod();
}
If you really wanted to get crazy I suppose you could make your own button custom control with a dependency property that is a delegate
, and you could then bind to a property that returns the same type of delegate
. And then in your custom control class you could invoke the delegate when it gets clicked.
There is always the standard ICommand, if you go that route this is how...
<Button Command={Binding CommandProperty} />
Use Kent Boogaart's DelegateCommand class from his blog post.
Then...
In the class you are binding to:
private ICommand _commandField;
public ICommand CommandProperty
{
get
{
if (_commandField == null) _commandField = new DelegateCommand(CommandMethod);
return _commandField;
}
}
private void CommandMethod()
{
// do stuff...
}
Yes for Button you will need to use ICommand established in your ComplexObject:
<Button Command="{Binding Path = CommandName}"/>
If your method is in the View Model that holds the ComplexObjects collection name your control or window Me and use something like this:
<Button Command="{Binding ElementName=Me, Path=DataContext.CommandName}" />
You could use click or preview mouse down, but if you're wanting to bind the method in XAML, you would still need to route that event to a command. It's just easier to bind the command.