2011-07-08 13 views
6

Me gustaría utilizar un datatemplate para mis columnas de cuadrícula de datos y tener un botón para cada elemento. Me gustaría que el artículo se elimine si el usuario hace clic en el botón. Estoy usando el patrón MVVM. ¿Cómo podría lograr esto?Cómo tener un botón en una plantilla de cuadrícula de datos que eliminará el elemento al hacer clic en

<DataGridTemplateColumn> 
    <DataGridTemplateColumn.CellTemplate> 
    <DataTemplate> 
     <Button Width="50" Content="Remove" Command="{Binding RemoveItemCommand}"/> 
    </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn> 

Respuesta

4
public class ItemViewModel 
{ 
    public ItemViewModel() 
    { 
    RemoveCommand = new MyCommand(Remove); 
    } 

    public event EventHandler ItemRemoved; 
    public ICommand RemoveCommand { get; private set; } 

    private void Remove() 
    { 
    // Whatever it takes to remove item from your data store 
    service.Remove(this.Data); 

    var removeItem = ItemRemoved; 
    if (removeItem != null) 
     removeItem(this, EventArgs.Empty); 
    } 
} 

public class ListViewModel 
{ 
    public ListViewModel(IEnumerable<ItemViewModel> items) 
    { 
    ItemVMs=new ObservableCollection<ItemViewModel>(items); 
    foreach (var item in ItemVMs) 
     item.ItemRemoved += RemoveSelectedItem; 
    } 

    public ObservableCollection<ItemViewModel> ItemVMs { get; private set; } 

    private void RemoveSelectedItem(object sender, EventArgs e) 
    { 
    var item = sender as ItemViewModel; 
    item.ItemRemoved -= RemoveSelectedItem; 
    ItemVMs.Remove(item); 
    } 
} 

Cada elemento de RemoveCommand estaría vinculado a su botón en su DataGrid. Parece que ya tienes esa parte hecha. Haga que la propiedad ItemVMs de ListViewModel sea la fuente de datos para su DataGrid.

+0

Hacer los elementos responsables de eliminarse es mucho más simple (y más fácilmente comprobable) que el enfoque de Will de vincular un comando en el elemento primario de los elementos. –

+0

Este enfoque fue más simple de implementar y funciona bien. Gracias –

4

La vista es responsable de esto. Simplemente puede usar codebehind para controlar la visibilidad de los elementos de la interfaz de usuario en respuesta a las acciones del usuario en la interfaz de usuario.

A veces, es mejor ser práctico que ser rígidamente dogmático.


Bueno, ahora que ha editado su pregunta, se convierte en una cuestión completamente diferente.

Su DataGrid debe estar vinculada a una colección de elementos.

Su botón debe estar vinculado a un comando en ViewModel, y CommandParameter debe ser el modelo al que está asociada la fila en particular.

<DataTemplate> 
     <Button Content="Remove" 
       Command="{Binding DataContext.RemoveItemCommand, 
           ElementName=theWindow}" 
       CommandParameter="{Binding}" /> 
</DataTemplate> 

Tenga en cuenta algunas cosas importantes aquí. Necesitamos, desde dentro de la plantilla, vincular a un ICommand en ViewModel. ViewModel es DataContext de la ventana. En este ejemplo, la ventana se llama 'theWindow' (x:Name="theWindow"). Como la fuente del Encuadernación es la ventana, la ruta de acceso debe apuntar al ViewModel en la propiedad DataContext en esa ventana.

Pasamos el modelo actual al que la fila DataGrid está vinculada en el comando. De esta forma, es triival eliminarlo de la colección en ViewModel.

public ObservableCollection<Model> Items {get;set;} 

public ICommand RemoveItemCommand {get;set;} 

// this method is called when RemoveItemCommand.Execute is called! 
public void Execute(object parameter) 
{ 
    Items.Remove(parameter as Model); 
} 

Esto supone que está utilizando una de las implementaciones estándar de ICommand delegadas que existen. Puede ver cómo esto es trivial de implementar, y dado que la colección es observable, una vez que haga clic en el botón y se elimine el Modelo, se le notificará al DataGrid el cambio en la colección y se eliminará esa fila.

+0

+1 por practicidad. – Stewbob

+0

Gracias Will, voy a probar esto y hacerle saber ... parece ser la solución adecuada para mí. –

+0

Parece que no está disparando el comando en el modelo de vista. Estoy usando MVVMLight relaycommand para configurar mi icommand. Cuando hago clic en el botón no pasa nada. El xaml es tal como lo tienes, como lo es el código de viewmodel. ¿Alguna idea de por qué no se disparará? –

2

Probablemente sea mejor utilizar los eventos enrutados estándar en el evento Click del botón en lugar de un comando. El evento click le permitirá recuperar la información sobre qué control se hizo clic, y luego también puede recuperar fácilmente el elemento primario del botón, para eliminar ese elemento.

Cuestiones relacionadas