8

I am developing a WPF application using the MVVM design pattern. In the application I have an ItemsControl that display several Buttons (number of buttons is not constant, according the logic flow of the application). The ItemsControl is binded to LinkedList in the ViewModel. I am able to define a Command for the Buttons and I able to get the Command handler within the ViewModel only if the Command has no parameters... I need to be able to know which button has been clicked and therefore I would like to have a Command with Parameter.

How do I need to define my View ? What is the Syntax for the CommandParameter and which parameter I can used to get the Button content ? What will be the Command signature in the ViewModel ?

Please note that I am using RelayCommand from MVVM Light. The relvant code of the View is here. Thanks in advance

<UserControl x:Class="Museum.Controls.CategoriesView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="130" d:DesignWidth="418">
    <UserControl.Resources>
        <DataTemplate x:Key="CategoriesButtonsTemplate">
            <Button Content="{Binding }" 
                    Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=DataContext.CategorySelectedCommand}" 
                    />
        </DataTemplate>
    </UserControl.Resources>
    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="50"></RowDefinition>
            <RowDefinition Height=" 40"></RowDefinition>
            <RowDefinition Height=" 40"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid x:Name="SubSubjectGrid" Grid.Row="0"></Grid>
        <Grid x:Name="CategoriesGrid" Grid.Row="1">
            <ItemsControl Grid.Row="1" 
                  ItemsSource="{Binding Path=CategoriesButtons}" 
                  ItemTemplate="{StaticResource CategoriesButtonsTemplate}" >
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"  HorizontalAlignment="Stretch"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
     </Grid>
        <Grid x:Name="SelectedCategoryGrid" Grid.Row="2"></Grid>
    </Grid>  
</UserControl>

3 Answers 3

10

You can simply use CommandParameter="{Binding }" like this

       <DataTemplate x:Key="CategoriesButtonsTemplate">
        <Button Content="{Binding }" 
                Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=DataContext.CategorySelectedCommand}" 
                CommandParameter="{Binding }" 
                />
    </DataTemplate>
Sign up to request clarification or add additional context in comments.

Comments

1

There is a generic RelayCommand class in MVVM Light toolkit which can handle command parameters. The non generic RelayCommand class ignores them. Here is a example:

First bind your CommandParameter property like Ahmed showed in his answer:

    <Button Content="{Binding}" 
            Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=DataContext.CategorySelectedCommand}" 
            CommandParameter="{Binding}" />

Lets say the linked list for the buttons in your viewmodel is a list of strings. Your button content and your CommandParameter are bound to one of your list items. Now create a generic RelayCommand propterty in your viewmodel:

 private RelayCommand<String> mOnClickCommand;

 public RelayCommand<String> ClickCommand
 {
     get { return mOnClickCommand; }         
 }

Instantiate it for example like this in your constructor:

 mOnClickCommand = new RelayCommand<string>(OnButtonClicked);

And finally in your method you will get the CommandParameter property as a method argument:

 private void OnButtonClicked(String _category)
 {
     Console.WriteLine(_category);
 }

Hope this is helpful.

Comments

0

You can use Interactivity and Iteractions libraries. In this case your should add this to your xaml code of a button:

<Button>
  <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
              <ei:CallMethodAction TargetObject="{Binding}" MethodName="OnClick"/>
        </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

And to viewModel:

public void OnClick(object sender, MouseEventArgs args)
{// your code }

1 Comment

Hi, Is this shall be inside the DataTemplate definition , within the Button ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.