Daniel Maurer
Daniel Maurer

Reputation: 166

UWP ListView Button MVVM Binding

I have a ListView that, right now opens a Popup on SelectedItem. What I want is that if the user decides to remove an Item from the List he can click the Button and it gets removed - right now the Button does fire, but how do I tell the Button in the VM what Item to delete - without "SelectedItem"? p.E..

<ListView 
 SelectedItem="{Binding...}"
 x:Name="lv">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Image Source="{Binding...}"/>
                <Button Command="{Binding ElementName=lv,Path=DataContext.RemoveXCommand}" />
            </Stackpanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

VM

public void RemoveXCommand()
    {
    foreach(var item in pseudo)
       {
       if(item.Name == ?????)
           pseudo.Remove(item);
       }
    }

Is there a way, or do I have to remove the opening of the Popup, and implement it as another Button, so I can use the SelectedItem to get the comparison?

Thank you.

EDIT1:

Thanks to Fruchtzwerg I got it working

public RelayCommand<string> RemoveXCommand{ get; private set; }

//... in then Constructor
RemoveXCommand = new RelayCommand<string>((s) => RemoveXCommandAction(s));

public void RemoveXCommand(object temp)
{
foreach(var item in pseudo)
   {
   if(item.Name == (string) temp)
       pseudo.Remove(item);
   }
}

Upvotes: 0

Views: 1037

Answers (1)

Fruchtzwerg
Fruchtzwerg

Reputation: 11389

You can pass the item you need to remove as CommandParameter

<Button Command="{Binding ElementName=lv, Path=DataContext.RemoveXCommand}"
        CommandParameter="{Binding}"/>

and remove it like

public void RemoveXCommand(object itemToRemove)
{
    pseudo.Remove(itemToRemove);
}

Your approach deleting the item by name is also possible. Bind the Name of the item as CommandParameter

<Button Command="{Binding ElementName=lv, Path=DataContext.RemoveXCommand}"
        CommandParameter="{Binding Name}"/>

and remove it like

public void RemoveXCommand(object nameToRemove)
{
    foreach(var item in pseudo)
    {
        if(item.Name == (string)nameToRemove)
        {
            pseudo.Remove(item);
        }
    }
}

Note that the second approach is removing all items having the name of the item you selected. The first approach removes only the item you selected because the specific instance is removed.

To allow a parameter in RelayCommand a new or modified implementeation of ICommand is required. Here is a possible solution:

public class ParameterRelayCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Func<bool> _canExecute;

    public event EventHandler CanExecuteChanged;

    public ParameterRelayCommand(Action<object> execute)
        : this(execute, null)
    { }

    public ParameterRelayCommand(Action execute<object>, Func<bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute();
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    public void RaiseCanExecuteChanged()
    {
        var handler = CanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

Upvotes: 2

Related Questions