Search code examples
c#wpfxamldatatemplateitemscontrol

How to add the same command to WPF buttons in ItemsControl


How would you add command to a wpf button that is part of ItemsControl and is modifying the ItemsSource itself?

So here is my XAML:

<ItemsControl ItemsSource="{Binding PluginVMs}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Button x:Name="btnStampDuplicate" 
                        Content="Duplicate this control"
                        Command="{Binding ?????????}"/>
                <!-- other stuff -->
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

And here is my viewmodel:

public ObservableCollection<PluginViewModel> PluginVMs
{
    get { return _pluginVMs; }
    set
    {
        if (_pluginVMs != value)
        {
            _pluginVMs = value;
            NotifyPropertyChanged("PluginVMs");
        }
    }
}

As you can see PluginVMs is collection of PluginViewModel. So I am aware that the Command that is available from the btnStampDuplicate should be implemented inside of PluginViewModel.

However, as the name duplicate suggest, I would like to make a duplicated copy of the currently generated PluginViewModel inside of PluginVMs. What is the best approach to give that kind of functionality to btnStampDuplicate?


Solution

  • it is not necessary to have a command in each item. you can use CommandParameter to pass an item which is a dupe source

    inside DataTemplate bind command using ElementName to access DataContext of a higher level

    View

    <ItemsControl Name="ListPlugins" ItemsSource="{Binding PluginVMs}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Button x:Name="btnStampDuplicate" 
                            Content="duplicate"
                            CommandParameter={Binding Path=.}
                            Command="{Binding Path=DataContext.DupeCmd, ElementName=ListPlugins}"
                    />
                    <!-- other stuff -->
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    ViewModel

    public class Vm
    {
        public ObservableCollection<PluginViewModel> PluginVMs
        {
            get { return _pluginVMs; }
            set
            {
                if (_pluginVMs != value)
                {
                    _pluginVMs = value;
                    NotifyPropertyChanged("PluginVMs");
                }
            }
        }
    
        public ICommand DupeCmd { get; private set; }
    }