2013-11-12 4 views
1

У меня есть наблюдаемый набор, который я прокручиваю, используя itemSource внутри моего представления. Каждый элемент в наблюдаемом собрании содержит кнопку, которая отправляет команду (openSessionCommand) в viewModel. Мой вопрос: как я могу отправить и ID обратно в viewModel, из которого нажата кнопка внутри элемента itemSource?Получение идентификатора кнопки, нажатой внутри itemSource?

<ItemsControl ItemsSource="{Binding AvailableSessions}" Margin="490,181,10.111,39.111"> 
<ItemsControl.ItemTemplate> 
    <DataTemplate > 
     <Border BorderBrush="Black" Background="Gainsboro" BorderThickness="1" Margin="2"> 
      <Grid Background="#FFECECEC"> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
       </Grid.RowDefinitions> 

       <Button Command="{Binding RelativeSource={RelativeSource FindAncestor, 
            AncestorType={x:Type UserControl}}, Path=DataContext.OpenSessionCommand}" 
         HorizontalAlignment="Left" Margin="10,10,0,0" 
         VerticalAlignment="Top" Width="243" Height="42"> 
        <TextBlock TextWrapping="Wrap"> 
         <Run Text="{Binding SessionName}"/><LineBreak/> 
         <Run Text="{Binding Genre}"/><Run Text=" - "/><Run Text="{Binding Tempo}"/> 
        </TextBlock> 
       </Button> 

       <Label Content="{Binding AdminUsername}" HorizontalAlignment="Left" 
        Margin="10,53,0,0" VerticalAlignment="Top" Width="243" Height="26"/> 
       <Label Content="{Binding Client1Username}" HorizontalAlignment="Left" 
        Margin="10,71,0,0" VerticalAlignment="Top" Width="243" Height="25"/> 

      </Grid> 
     </Border> 
    </DataTemplate> 
</ItemsControl.ItemTemplate> 
<ItemsControl.Template> 
    <ControlTemplate TargetType="ItemsControl"> 
     <ScrollViewer CanContentScroll="True"> 
      <ItemsPresenter/> 
     </ScrollViewer> 
    </ControlTemplate> 
</ItemsControl.Template> 

<ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <VirtualizingStackPanel/> 
    </ItemsPanelTemplate> 
</ItemsControl.ItemsPanel> 

DelegateCommand:

public class DelegateCommand : ICommand 
{ 
    private readonly Action _command; 
    private readonly Func<bool> _canExecute; 
    public event EventHandler CanExecuteChanged 
    { 
     add { CommandManager.RequerySuggested += value; } 
     remove { CommandManager.RequerySuggested -= value; } 
    } 

    public DelegateCommand(Action command, Func<bool> canExecute = null) 
    { 
     if (command == null) 
     throw new ArgumentNullException(); 
     _canExecute = canExecute; 
     _command = command; 
    } 

    public void Execute(object parameter) 
    { 
     _command(); 
    } 

    public bool CanExecute(object parameter) 
    { 
     return _canExecute == null || _canExecute(); 
    } 
} 

ICommand:

public ICommand OpenSessionCommand { get 
    { return new DelegateCommand(OpenSession); } 
} 


public void OpenSession() 
{ 
    ContinueReceiving = false; 
    dispatcherTimer.Stop(); 

    Messenger.Default.Send<NavigateMessage>(
     new NavigateMessage(SessionViewModel.ViewName, this)); 
} 
+2

Посмотрите на CommandParameter –

ответ

2

Используйте CommandParameter. Использование {Binding} передает объект в наблюдаемую коллекцию, которая была нажата. Больше на MSDN

<Button Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.OpenSessionCommand}" CommandParemeter="{Binding}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="243" Height="42"> 
    <TextBlock TextWrapping="Wrap"> 
     <Run Text="{Binding SessionName}"/><LineBreak/> 
     <Run Text="{Binding Genre}"/><Run Text=" - "/> 
     <Run Text="{Binding Tempo}"/> 
    </TextBlock> 
</Button> 

Вам также нужно настроить метод OpenSessionCommand подпись принять ваш параметр, но это будет зависеть от того, что реализация команд вы используете.

UPDATE

Ниже приводится общая реализация DelegateCommand, который принимает параметр.

public class DelegateCommand<T> : ICommand where T : class 
{ 
    private readonly Action<T> _command; 
    private readonly Func<T, bool> _canExecute; 
    public event EventHandler CanExecuteChanged 
    { 
     add { CommandManager.RequerySuggested += value; } 
     remove { CommandManager.RequerySuggested -= value; } 
    } 

    public DelegateCommand(Action<T> command, Func<T, bool> canExecute = null) 
    { 
     if (command == null) 
      throw new ArgumentNullException(); 
     _canExecute = canExecute; 
     _command = command; 
    } 

    public void Execute(object parameter) 
    { 
     _command(parameter as T); 
    } 

    public bool CanExecute(object parameter) 
    { 
     return _canExecute == null || _canExecute(parameter as T); 
    } 
} 

Теперь, когда вы определяете ICommand это должно быть что-то вроде этого:

public ICommand OpenSessionCommand { get { return new DelegateCommand<Button>(OpenSession); } } 

    public void OpenSession(Button button) 
    { 
     ContinueReceiving = false; 
     dispatcherTimer.Stop(); 

     Messenger.Default.Send<NavigateMessage>(new NavigateMessage(SessionViewModel.ViewName, this)); 
    } 
+0

Я обновил свой вопрос с моей реализации DelegateCommand. Я вижу, что вы имеете в виду, когда добавляю точку останова над «Executed» - я вижу, что элемент передан как параметризованный. Как мне получить OpenSession()? – user547794

+0

OpenSession автоматически получит параметр. Когда вы создаете canececute и execute, определяете их как (o) => Button b = o в качестве кнопки (в качестве примера). –

1

Я использую нечто подобное из в ListBox с контекстным меню.

<ContextMenu> 
    <MenuItem Header ="Edit Exercise" 
       Command="{Binding EditExercise_Command}" 
     CommandParameter="{Binding SelectedExercise}" 
/> 

Таким образом, вызываемый метод получает упражнение, которое я нажимал правой кнопкой мыши в качестве параметра.

Вы можете передать кнопку :)

Смежные вопросы