2017-02-03 12 views
1

Я пытаюсь привязать SelectionChanged к команде в коде ниже.EventSetter в DataGridComboBoxColumn throws NullReferenceException

<EventSetter Event="SelectionChanged" Handler="{Binding MyCommand}" /> 

Но, к сожалению, я в NullReferenceException получаешь в InitializeComponent();

Что может быть проблема? Программа работает, если я удаляю указанную выше одну строку.

<StackPanel> 

    <DataGrid ItemsSource="{Binding Items}" 
       AutoGenerateColumns="False"> 
     <DataGrid.Columns> 

      <DataGridTextColumn Header="Name" 
           Binding="{Binding Name}"/> 

      <DataGridComboBoxColumn Header="Color" 
            SelectedItemBinding="{Binding Color}"> 
       <DataGridComboBoxColumn.ElementStyle> 
        <Style TargetType="ComboBox"> 
         <Setter Property="ItemsSource" Value="{Binding Colors}"/> 
        </Style> 
       </DataGridComboBoxColumn.ElementStyle> 
       <DataGridComboBoxColumn.EditingElementStyle> 
        <Style TargetType="ComboBox"> 
         <Setter Property="ItemsSource" Value="{Binding Colors}"/> 

         <EventSetter Event="SelectionChanged" Handler="{Binding MyCommand}" /> 


        </Style> 
       </DataGridComboBoxColumn.EditingElementStyle> 
      </DataGridComboBoxColumn> 
     </DataGrid.Columns> 
    </DataGrid> 

    <Button Command="{Binding MyCommand}" Width="100" Height="100" Content="Change"/> 
</StackPanel> 


    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
     InitializeComponent(); 

     this.DataContext = new Data(); 
     } 
    } 


    public class Data 
    { 
     /// <summary> 
     /// A collection that stores the data required 
     /// to populate the <seealso cref="DataGrid"/> for sheets in paste window. 
     /// </summary> 
     private ObservableCollection<Item> _items; 
     public ObservableCollection<Item> Items 
     { 
     get { return _items; } 

     } 

     private ICommand _myCommand; 
     public ICommand MyCommand 
     { 
     get 
     { 
      return _myCommand ?? (_myCommand = new CommandHandler(() => Change(), _canExecute)); 
     } 
     } 
     private bool _canExecute; 

     public Data() 
     { 
     _canExecute = true; 
     _items = new ObservableCollection<Item>(); 
     _items.Add(new Item("A")); 
     _items.Add(new Item("B")); 
     } 

     public void Change() 
     { 
     _items[0].Name = "D"; 
     } 
    } 

    public class CommandHandler : ICommand 
    { 
     private Action _action; 
     private bool _canExecute; 
     public CommandHandler(Action action, bool canExecute) 
     { 
     _action = action; 
     _canExecute = canExecute; 
     } 

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

     public event EventHandler CanExecuteChanged; 

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

    public class Item : INotifyPropertyChanged 
    { 
     private string _name; 
     public string Name 
     { 
     get { return _name; } 
     set 
     { 
      _name = value; 
      RaisePropertyChanged("Name"); 
     } 
     } 
     public string Color { get; set; } 


     private IList<string> _colors; 

     public event PropertyChangedEventHandler PropertyChanged; 

     public IList<string> Colors 
     { 
     get { return _colors; } 
     } 


     public Item(string name) 
     { 
     _name = name; 
     _colors = new List<string> { "Green", "Blue" }; 
     Color = _colors[0]; 
     } 

     private void RaisePropertyChanged(string propertyName) 
     { 
     var handler = PropertyChanged; 
     if (handler == null) return; 

     handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

ответ

1

EventSetter ожидает от вас указать существующее событие из файла codebehind (xaml.cs). Он не работает с привязками. Поэтому создайте соответствующий обработчик событий внутри MainWindow.xaml.cs и укажите его в EventSetter или используйте Interaction.Triggers from Blend, MvvmLight

<Window 
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:command="http://www.galasoft.ch/mvvmlight" > 
<i:Interaction.Triggers> 
      <i:EventTrigger EventName="Loaded"> 
      <command:EventToCommand 
       Command="{Binding MyCommand}" 
       PassEventArgsToCommand="False" /> 
      </i:EventTrigger> 
</i:Interaction.Triggers> 
</Window> 
+0

Спасибо. Не могли бы вы рассказать мне, как вызвать команду из кода MainWindow? – Vahid

+0

data.MyCommand.Execute (null)? – Vahid

+0

Ну, вы можете использовать этот.DataContext для своего типа и вызывать команду из вашей ViewModel, как вы указали. Но это плохой дизайн, правильный подход будет использовать EventToCommand. – 3615