There is an abstract class Shape :

 abstract class Shape { public string Name {get;set} } 

And the various classes of shapes that are inherited from Shape - Triangle , Circle , Square .

There is also a collection of shapes that binds to the ListBox :

 public ObservableCollection<Shape> Shapes{get;set;} = new ObservableCollection<Shape>() { new Triangle {Name = "Треугольник"}, new Circle {Name = "Круг"}, new Circle {Name = "Круг"}, new Square {Name = "Квадрат"}, } 

Each object in the ListBox is represented by the Name property of the object and a button to which the command to remove an item from the collection is bound. Team one for all elements.

 <ListBox.ItemTemplate> <DataTemplate> <Border> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding Name}" /> <Button Grid.Column="1" Content="x" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=DataContext.RemoveShapeCommand}" CommandParameter="{Binding}" /> </Grid> </Border> </DataTemplate> </ListBox.ItemTemplate> 

The question is: The elements can have the same properties. How, in this case, to find the desired item that you want to delete?

Is it possible to get the index of the element that caused the command?

  • 2
    I think the easiest option for you is to add another field GUID or ID. Or you can pass the element itself through the Comman parameter and get the element from the parameters of the RemoveShapeCommand command method. You can also use SelectedItem, if this option suits you - user2455111
  • @ user2455111, With Id option, yes. Thank. - trydex

2 answers 2

If your Equals function is not overloaded, the easiest way is to delete by the element itself . The index is almost never needed. When deleting, the desired element will be determined using Equals , and therefore, the same properties or not will not be taken into account.

  • Did not know this. Thank! - trydex
  • @maxwellL Please! - VladD

This option is to remove multiple parameters. If at your grid selection of several lines is forbidden and you delete one line at a time. Then use the SelectedItem property for the grid:

 var tempItem = SelectedItem; SelectedItem = myList.FirstOrDefault(); myList.Remove(tempItem); 

Otherwise:

xaml

 <Button Content="Delete" Command="{Binding Path=DeleteCommand, Mode=OneTime}" CommandParameter="{Binding ElementName=MyGridName, Path=SelectedItems}" Width="100" Margin="10" /> 

command

 public ICommand DeleteCommand { get { return _deleteCommand ?? (_deleteCommand = new CollectionCommandDelegate<MyListType>( collection => { var myDeleteParameters = collection != null ? collection.ToArray() : null; if(myDeleteParameters!= null) foreach(var myparam in myDeleteParameters) myList.Remove(myparam); }; } } 

Well, and CollectionCommandDelegate public class CollectionCommandDelegate: ICommand {private readonly Action> _invoker; private readonly Func, bool> _predicate; private bool _hasChange;

  public CollectionCommandDelegate(Action<IEnumerable<T>> invoker) { _invoker = invoker; _predicate = arg => true; } public CollectionCommandDelegate(Action<IEnumerable<T>> invoker, Func<IEnumerable<T>, bool> predicate) { _invoker = invoker; _predicate = predicate; } public void Execute(object parameter) { _invoker.Invoke(getParameter(parameter)); } public bool CanExecute(object parameter) { var newState = _predicate.Invoke(getParameter(parameter)); if (newState != _hasChange) { _hasChange = newState; if (CanExecuteChanged != null) CanExecuteChanged(this, EventArgs.Empty); } return _hasChange; } private IEnumerable<T> getParameter(object parameter) { return ((IEnumerable)parameter).Cast<T>(); } public event EventHandler CanExecuteChanged; }