The program uses several ItemsControl with an overridden style, the elements of which are buttons that do roughly the same thing: by clicking on a button, the selected item should be removed from the collection bound to the ItemsSource .

Due to the fact that different collections are attached, for each ItemsControl I make my removal team. And each ItemsControl in my looks like this:

  <ItemsControl ItemsSource="{Binding MyCollection}" > <ItemsControl.Style> <Style TargetType="{x:Type ItemsControl}" BasedOn="{StaticResource ItemsControlMainStyle}"> <Setter Property="ItemContainerStyle"> <Setter.Value> <Style TargetType="ContentPresenter"> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <Button Content="{Binding}" Command="{Binding ElementName=mainWindow, Path=DataContext.OperationsVM.RemoveElementCommand}" /> </DataTemplate> </Setter.Value> </Setter> </Style> </Setter.Value> </Setter> </Style> </ItemsControl.Style> </ItemsControl> 

That is, I supplement the main ItemsControlMainStyle style and bind the necessary command. The code is very bulky. Intuitively, it seems that you can make everything more concisely and bring this piece of code with the style and binding of the commands into ItemsControlMainStyle , and take the necessary command from the property. But with the implementation of this approach, I have problems, because ItemsControl does not have a Command property.

Tell me how to do this (and can it)?

  • Not quite clear what is meant by Из-за того, что привязываются разные коллекции are tied - user227049
  • @FoggyFinder; There are 4 different ObservableCollection in the ViewModel , which are bound to 4th different ItemsControl . Each element is represented by a button, by clicking on which the element should be removed from the associated collection. - trydex

2 answers 2

Well, the standard hack for such cases is to use Tag .

It turns out that's how. In ItemsControlMainStyle add

 <Setter Property="ItemContainerStyle"> <Setter.Value> <Style TargetType="ContentPresenter"> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <Button Content="{Binding}" Command="{Binding Tag, RelativeSource={RelativeSource FindAncestor, AncestorType=ItemsControl}}" /> </DataTemplate> </Setter.Value> </Setter> </Style> </Setter.Value> </Setter> 

Now you can bind the command to ItemsControl 'at:

 <ItemsControl ItemsSource="{Binding MyCollection}" Style="{StaticResource ItemsControlMainStyle}" Tag="{Binding DeleteCountryCommand}"/> 

By the way, it is not clear why you are using the ItemContainerStyle , and not the ItemTemplate :

 <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate> <Button Content="{Binding}" Command="{Binding Tag, RelativeSource={RelativeSource FindAncestor, AncestorType=ItemsControl}}" /> </DataTemplate> </Setter.Value> </Setter> 

    Illustration to the code

    ViewModel is connected in XAML

     <Window.DataContext> <local:MainViewModel /> </Window.DataContext> 

    A list with buttons such

      <ListBox Height="284" Canvas.Left="135" Canvas.Top="27" Width="186" ItemsSource="{Binding StrList}" > <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Margin="5"> <TextBlock Text="{Binding Mode=OneWay}" /> <Button FontFamily="Segoe UI Symbol" FontSize="12" Content="&#xE106;" Margin="10,0" Command="{Binding DataContext.DeleteCountryCommand, ElementName=window}" CommandParameter="{Binding Mode=OneWay}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> 

    In ViewModel

    property for list

     private ObservableCollection<string> _StrList; public ObservableCollection<string> StrList { get { return _StrList; } set { _StrList = value; PropertyChanged(this, new PropertyChangedEventArgs(nameof(StrList))); } } 

    Command to remove

     private RelayCommand<string> _DeleteCountryCommand; public RelayCommand<string> DeleteCountryCommand { get { return _DeleteCountryCommand = _DeleteCountryCommand ?? new RelayCommand<string>(OnDeleteCountry, CanDeleteCountry); } } private bool CanDeleteCountry(string arg) { return true; } private void OnDeleteCountry(string obj) { StrList.Remove(obj); } 
    • one
      The question was how to make a team in style and for this style to be universal. I repeat, I have 4 collections and 4 ItemsControl and the command to delete an item for each of the collections is different. This is the difficulty for me, which accounts for the part of the style where the team is binge, to endure. - trydex
    • You calmly, logically think about it: "... how to make a team in style and for this style to be universal." and how it relates to this: "and the command to delete an item for each of the collections has its own." Therefore, since the team has its own, it cannot be forgotten in a universal style. Team building must be independent of style. - Bulson
    • The fact is that the team does not bind itself directly, but through the property of the parent element. Something like <ItemsControl Command="{Binding RemoveCommand}" /> . And in the style we are already taking this command to remove an item from the collection. The question is how to do it. - trydex
    • Sorry, but all this reminds me: "... we are not looking for easy ways ...", "we have no problems except those that we have invented ourselves." - Bulson
    • The problem is that it is 1) copying the code 2) cumbersome code. - trydex