How to bind a button on wpf grid to a method on MVVM when I am using caliburn micro
Asked Answered
S

2

6

I have a Grid on a wpf window which I want to add the capability that user can delete some of the items by clicking on a delete button. The application uses Calibrun Micro to bind view to ViewModel.

My question?

1- Is it a good idea to use a button to delete an item from a grid in WPF?

2- How can I bind a button to a method on VM and in the methd get a pointer to the item that should be deleted?

Edit1

I added the buttons in this way to datagrid:

<DataGridTemplateColumn Width="100">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Button Content="Delete" cal:Message.Attach="DeleteFromList($dataContext)" />
         </DataTemplate>
     </DataGridTemplateColumn.CellTemplate>
 </DataGridTemplateColumn>

and c# code follow:

 public void DeleteFromList(object tmp)
    {

    }

But the buttons on datagrid are disabled and clicking on them doesn't fire DeleteFromList method (I checked using debugger).

Why they are disabled? How can I make them enabled?

Swerve answered 24/9, 2013 at 11:28 Comment(0)
P
9

This depends on how your button is placed - is there a single 'delete' button or have you added a button per row in the grid (are we talking DataGrid or just Grid?)

Assuming you are talking about DataGrid, you can easily just add an action message command to the button and pass through the item which is being deleted to the message handler on the VM

e.g. in the VM

public class MyViewModel
{
    public DataItemCollectionTypeName ItemCollection { get; set; }

    public void DeleteItem(DataItemTypeName item)
    {
        ItemCollection.Remove(item);
    }
}

Assuming ItemCollection is bound to the grid, the button XAML may look like this:

<Button cal:Message.Attach="[Click] = [DeleteItem($datacontext)]" />

You may also need to set Action.TargetWithoutContext (it should be bound to the VM) if this is a templated row, as otherwise CM will not be able to locate the VM to invoke the action message on

If you have a single button that isn't contained within the grid you can always target the grids SelectedItem in the action message

<DataGrid x:Name="SomeDataGrid"></DataGrid>
<Button cal:Message.Attach="[Click] = [DeleteItem(SomeDataGrid.SelectedItem)]" />

It may be (and probably is) the default property that CM will look at so you may not need to specify the property name unless you have modified default conventions

<DataGrid x:Name="SomeDataGrid"></DataGrid>
<Button cal:Message.Attach="[Click] = [DeleteItem(SomeDataGrid)]" />

Edit

To clarify: In order for CM to find a VM to call the DeleteItem method it uses the DataContext of the current item. In the case of an ItemsControl derived control, the datacontext for each item points to the item being bound, not the ViewModel.

In order to give CM a hint as to which object it should try to resolve the DeleteItem method on, you can use the Action.TargetWithoutContext attached property, which applies a target object for action messages without changing the DataContext of the bound row/item

You can use element name syntax to point to the correct place:

In this example I've used a grid as the root element and named it LayoutRoot, then I've pointed the action message target to LayoutRoot.DataContext (which will be the ViewModel) using ElementName syntax. You can use any method (AncestorType or whatever)

<Grid x:Name="LayoutRoot">
    <DataGridTemplateColumn Width="100">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <Button Content="Delete" cal:Message.Attach="DeleteFromList($dataContext)" cal:Action.TargetWithoutContext="{Binding DataContext, ElementName=LayoutRoot}" />
             </DataTemplate>
         </DataGridTemplateColumn.CellTemplate>
     </DataGridTemplateColumn>
</Grid>

That should then work!

Peyter answered 24/9, 2013 at 11:37 Comment(2)
Thanks. Can you please give me more information about "You may also need to set Action.TargetWithoutContext (it should be bound to the VM) if this is a templated row, as otherwise CM will not be able to locate the VM to invoke the action message on" since my button is disable and clicking on it doesn't fire my method on VM.Swerve
thank you! I had a similar question ( #19680304 ) and this made it clear! I also posted my solutionHerbart
S
1

You could do something like this...

<Button cal:Message.Attach="[Event MouseEnter] = [Action Save($this)]"> 

Check the docs as they will explain what you need to do and should answer your question: link

Sesame answered 24/9, 2013 at 11:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.