2

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.

H.B.
  • 166,899
  • 29
  • 327
  • 400
trickdev
  • 627
  • 1
  • 7
  • 14
  • @DJ KRAZE - I'm not sure how that would help - I'm looking to bind to the complex object, not the code behind. – trickdev Feb 03 '12 at 15:25
  • 1
    here is something that might help then If I understand correctly Button in that since doesn't truly support Binding but this site may help clarify http://connect.microsoft.com/VisualStudio/feedback/details/472932/wpf-commandparameter-binding-should-be-evaluated-before-command-binding | here is a similar post on StackOverFlow that will give you 3 possible options as well http://connect.microsoft.com/VisualStudio/feedback/details/472932/wpf-commandparameter-binding-should-be-evaluated-before-command-binding – MethodMan Feb 03 '12 at 15:26
  • @DJ KRAZE Thanks, but same link posted twice there. – trickdev Feb 03 '12 at 15:32
  • 1
    http://stackoverflow.com/questions/7882125/button-inside-a-wpf-list-view-data-grid Sorry.. Dang Copy Paste.. – MethodMan Feb 03 '12 at 15:33

3 Answers3

5

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();
}
Lukazoid
  • 19,016
  • 3
  • 62
  • 85
  • Like the answer, I cannot get the binding to work at this point – trickdev Feb 03 '12 at 16:16
  • Got it, but Im not using RelativeSource just {Binding ElementName=nameOfListView, Path=DataContext.DoSomethingCommand} – trickdev Feb 03 '12 at 16:42
  • Answer could also use some explanation around DelegateCommand, I have used them before, but others may not have. Thanks! – trickdev Feb 03 '12 at 16:43
  • I'm glad you got it working, your solution is probably more efficient than traversing the tree too. – Lukazoid Feb 03 '12 at 16:45
2

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...
}
KurToMe
  • 166
  • 1
  • 6
  • 1
    I think the asker is trying to avoid using an `ICommand` on each `ComplexObject` and is looking for a way to directly invoke a method. – Lukazoid Feb 03 '12 at 15:44
0

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.

Josh
  • 2,955
  • 1
  • 19
  • 28