How would you know which element of an ItemsContro

2019-08-04 03:17发布

问题:

Let's say I currently have an ItemsControl whose DataTemplate is a bunch of buttons. I'm wiring up these buttons' click events, but how am I to know which button was clicked? Should I not use a ItemsControl?

I'm trying to have no code-behind, but being pragmatic may be necessary.

<ItemsControl>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Margin="10">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding ItemsControlButtonClicked, Mode=OneWay}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

回答1:

If you want to know what Item was clicked, then pass {Binding } as the CommandParameter and it will pass the selected object to your Command

If you want to know what Button was clicked, I would do that in the code-behind since ViewModels do not need to know anything about the UI, and that includes buttons.

Also since your control is a Button, you should use the Command property instead of a Click trigger.

<Button Command="{Binding ItemsControlButtonClicked}" />


回答2:

You can send parameters along with the command and based on these parameters you can find out which button was clicked



回答3:

In my project I also use the MVVM Light I has an dropdown with collection of items, and a button which user press and action depend on selected item from drop down you should create a Relay command with parameter look at the example from my code

  public RelayCommand<Project> StartTimer { get; private set; }//declare command

   StartTimer = new RelayCommand<Project>(OnStartTimer);

    private void OnStartTimer(Project project)
    {

        if (project != null)
        {

            currentProject = project;

            if (!timer.IsTimerStopped)
            {
                timer.StopTimer();
            }
            else
            {
                Caption = "Stop";
                timer.StartTimer();
            }
        }

on the view I bind the drop down with collection of class Project and for button command parameter I bind the selected item form drop down look at the code

   <ComboBox Name="projectcomboBox" ItemsSource="{Binding Path=Projects}"    IsSynchronizedWithCurrentItem="True" DisplayMemberPath="FullName"
              SelectedValuePath="Name"  SelectedIndex="0"  >
    </ComboBox>
      <Button Name="timerButton" Content="{Binding Path=Caption}" Command="{Binding Path=StartTimer}" 
                CommandParameter="{Binding ElementName=projectcomboBox, Path=SelectedItem}"  ></Button>

pay attention to Command and CommandParameter binding

also you can use this approache not only for drop down



回答4:

Well, you can use the Sender.DataContext which is the actual data.



回答5:

Create command properties in your view model class (using Josh Smith's RelayCommand pattern is the simplest way to do this) and bind each button's Command to the appropriate one. Not only is this straightforward to do and simple to maintain, it also gives you an easy way of implementing the enable/disable behavior when you need to.



标签: c# wpf xaml mvvm