问题
I'm trying to bind the SelectionChanged to a command in the code below.
<EventSetter Event="SelectionChanged" Handler="{Binding MyCommand}" />
But unfortunately I'm gettin an NullReferenceException at InitializeComponent();
What can be the problem? The program works if I remove the above single line.
<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 expects from you to indicate existing event from codebehind file (xaml.cs). It doesn't work with bindings. So create corresponding event handler inside MainWindow.xaml.cs and indicate it in EventSetter or use 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>
来源:https://stackoverflow.com/questions/42023994/eventsetter-in-datagridcomboboxcolumn-throws-nullreferenceexception