2012-02-09 3 views
3

Учитывая следующий XAML ...ComboBox, Button и ICommand привязок (MVVM иш)

<ComboBox x:Name="advisoriesComboBox" 
    DisplayMemberPath="Name" 
    ItemsSource="{Binding Path=Advisories}" 
    SelectedItem="{Binding Path=SelectedAdvisory}" /> 

<Button Command="{Binding Path=AddAdvisoryCommand}" 
    CommandParameter="{Binding ElementName=advisoriesComboBox, Path=SelectedItem}" 
    CommandTarget="{Binding ElementName=advisoriesComboBox}" 
    Content="Add..." /> 

Я ищу способ, чтобы связать ComboBox, Button и команды таким образом, что, когда значение изменений ComboBox, CanExecute вызывается в Command. Чистый эффект от того, что я хочу, - это возможность включать и отключать кнопку на основе того, какой элемент выбран в списке, и я бы предпочел сделать это, используя интерфейс ICommand.

Я делал это в прошлом, используя свойство «SelectedAdvisory» на виртуальной машине и вручную вызывая RaiseCanExecuteChanged для объектов команды (я использую экземпляры DelegateCommand из PRISM v4), но я уверен, что есть лучшее и более чистый способ сделать это, используя только XAML.

Спасибо.

EDIT: Кроме того, есть ли более простой способ ссылки на ComboBox с Button? Я попытался использовать RelativeSource PreviousData, но не смог заставить его работать, следовательно, использование x:Name.

Еще раз спасибо.

+0

То, что вы делали в прошлом, выглядит довольно хорошо для меня. Я не уверен, что XAML - лучшее место для этого. – ken2k

ответ

1

Теперь у вас есть настройка, что я буду делать. Если команда может выполнить или нет, это бизнес-правило, что означает, что она должна обрабатываться с ViewModel, а не View.

Единственное различие я сделать это, чтобы поднять CanExecuteChanged() в PropertyChange случае вашей ViewModel, вместо set метода SelectedAdvisory

void MyViewModel() 
{ 
    this.PropertyChanged += MyViewModel_PropertyChanged; 
} 

void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    switch(e.PropertyName) 
    { 
     case "SelectedAdvisory": 
      ((DelegateCommand)AddAdvisoryCommand).RaiseCanExecuteChanged(); 
      break; 
    } 
} 

Я предпочитаю, чтобы сохранить логику из моих геттеры/сеттеры, если это возможно , и использование события PropertyChanged позволяет мне видеть все, что происходит, когда свойства меняются в одном месте.

Конечно, если вы используете RelayCommand вместо DelegateCommand, вам не нужно вручную поднимать CanExecuteChanged() при изменении свойств, так как это происходит автоматически.

Вы также можете упростить свой XAML, предоставляя обе им одинаковые DataContext. Button не обязательно должен ссылаться на ComboBox.

<ComboBox 
    DisplayMemberPath="Name" 
    ItemsSource="{Binding Path=Advisories}" 
    SelectedItem="{Binding Path=SelectedAdvisory}" /> 

<Button Command="{Binding Path=AddAdvisoryCommand}" 
    CommandParameter="{Binding SelectedAdvisory}" 
    Content="Add..." /> 
+0

INotifyPropertyChanged - это то, как я обрабатываю его сейчас, единственное отличие состоит в том, что мне требуются все объекты команд для запроса CanExecute для всех изменений свойств, а не для выборочного выборочного запроса. Благодарю. –

+1

Согласен. Если вы хотите «ярлык», то «RelayCommand» - хорошая реализация «ICommand». Вместо этого я предпочитаю «DelegateCommand» ... «RelayCommand» выполняется слишком часто, потому что он связан с событием CommandManager.RequerySposed. Это делает отладку раздражающей. –

2

я бы все в ViewModel, мне кажется, лучше всего, когда дело доходит до модульного тестирования

<ComboBox x:Name="advisoriesComboBox" 
    DisplayMemberPath="Name" 
    ItemsSource="{Binding Path=Advisories}" 
    SelectedItem="{Binding Path=SelectedAdvisory}" /> 

<Button Command="{Binding Path=AddAdvisoryCommand}" 
    Content="Add..." /> 

В.М.

private bool CanAddExecute() 
{ 
    return this.SelectedAdvisory != null; 
} 

private void AddExecute() 
{ 
    if(!CanAddExecute()) 
     return; 

    //do here what you want, your information for the selected item is in this.SelectedAdvisory 
} 

код рукописные, так что может быть какой-то ошибки.

+0

Это работает, но я вроде как идея обработчика команды передается объект для работы (согласно предложению Рейчелса). Благодарю. –

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